If

(Engine-Level Function)

Description: Trigger to perform an action. It changes the active state in a module instance or executes a script or both.
Returns: Nothing
Usage: Steady State only.
Function Groups: Logic Control
Related to: IfElse | IfOne | IfThen | Cond
Format:
If Trigger Destination; { Optional change to state, Destination }
[
  { Optional script  code }
]
Parameters:  
Trigger
Required. Any logical expression. If false, nothing happens. If true, the action is performed, and any functions in the Trigger expression that may be reset are automatically reset.
Destination
Optional. Destination is not an expression, it is the text name of a state. If provided, it must be a legal name of a state in the module where this action is defined.
It is not possible to change to a state in another module. Each object must have one (and only one) active state, unless the module has no states defined.
Comments:

Do not use this function in expressions that you write in tags or Idea Studio objects. The If statement is for use only in full VTScada scripting modules.

An action may have a Destination, a Script, or both. (Or neither, although it does not make sense to have neither.)

Note that an object is not in any active state while it is executing a script that is changing states. The object leaves the old state when the script starts, and the object enters the new state when the script ends.

Script is a list of functions and statements, ending in semicolons, contained by square brackets. The Script is optional and may be omitted. There is no limit to the number of statements in Script (other than RAM). If the script is omitted, the square brackets should also be omitted. A script's statements are executed in order, from top to bottom. While a script is executing, no other statements in the current script thread can execute until this script is complete. (Script running in another bubble can run fully in parallel across multiple processor cores.)

Any function used within a script block must be one that can run in a script. (Refer to the Usage description of the function.) The IF statement itself and the expression used for the trigger run in steady state, therefore any function used in the trigger must be legal in steady state.

Examples:

When the current local time is after 12 PM, the state MorningState is stopped and the state AfternoonState is started.

{ Use an If to switch states }

MorningState [ 
  If Now(3600)/3600 >= 12 AfternoonState;
  { ... code to run or display during the morning ... }
] { End state MorningState }

AfternoonState [
...

The next example counts five-second intervals. This illustrates a use for AbsTime() , which is a member of the group of the Latching and Resetting Functions. These are well-suited to be conditionals for If statements because they automatically reset themselves to FALSE immediately after triggering the If.

{ Use an If to control when a set of statements execute }
TakeFive [
If AbsTime(1, 5, 0);
[ FiveCounter++; { ... other code to run every 5 seconds ... } ] ]

The next example is of an extremely common construct in VTScada modules. An initialization state assigns values to variables, then control is passed to the main state. The script in the initialization state runs exactly once before the state transfer, even though the conditional test is "If TRUE...".

[ { Declare variables... }
  StartTime        { Will hold a timestamp for when the module begins }
  { ... Other variables as needed }
]
Init [
  If 1 Main;
  [
    StartTime = CurrentTime(1);    { Set StartTime to the current UTC time }
  ]
]
Main {
{ ... Code that requires a start time ... }

When using an IF to run a script block that does not then proceed to another state, use care to avoid If 1 conditions. Consider the following variation on an earlier example:

{ An example of poorly written code }
[ { Declare and initialize the variable... }
  AfternoonCount = 0      { Count of morning to noon transitions };
  AnotherNoon    = FALSE  { Boolean to indicate whether it is afternoon };
]
Main [
  AnotherNoon = Now(3600)/3600 >= 12 { Check every hour whether it's after 12 };
  If AnotherNoon;
  [
    AfternoonCount++    { Increment the afternoon count };
  ]
]

This is an example of what to AVOID!

This action will trigger over and over again until midnight. This is called an "If 1" condition and will degrade system performance to a small percentage of its normal potential. All the time AnotherNoon is true (1), AfternoonCount will increase by one at a very rapid rate. This is because there is no destination state and the action remains active for 12 hours. The trigger is checked again and again.

To avoid this, use the following:

   { Only run script when value changes }
  If Watch(1, AnotherNoon);
  [
    { Is this the first or a following AfterNoon? }
    IfThen(AnotherNoon,
      AfternoonCount += 1;
    );
  ]

Refer to "Latching and Resetting Functions" for further information.