Understanding How Scripts Operate in InTouch

This describes how the script engine operates within the Wonderware® InTouch™ environment. This is intended for all Wonderware employees and distributors, OEMs, VARs, MIS/MES professionals, system integrators, application engineers, system developers, and system administrators of InTouch applications. You should have an advanced programming competency level in order to apply some of the features shown in this issue.

The testing for this article was completed using InTouch Release 5.6 under Microsoft Windows 95; however the results should be accurate for InTouch releases 5.0b through 5.6.

Disclaimer The information contained here is correct based on the scripting examples and demonstration application that were used in this article. However, your results and experiences in using the InTouch script engine may vary due to circumstances outside the realm of the examples that are shown here.

Installing the Associated InTouch Test Applications

This article references two InTouch test applications that demonstrates the various points made in this article. These applications will run under InTouch Release 5.6 or later.

  • Use the Testscr1.zip file for the InTouch Test Script application #1.
  • Use the Testscr2.zip file for the InTouch Test Script application #2.

Overview

The InTouch script engine encompasses and operates a number of script types in a seamless manner. Programmers may occasionally encounter problems with complex scripts, especially when they execute one type of script from another. This Tech Note will help you think out your scripts and understand how the script engine works so that when you write your scripts, you will do so with minimal errors.

Writing Scripts

The easiest way to write an InTouch script—especially if it is complex—is to first flowchart what you want to accomplish. However, keep in mind that your flowchart cannot have any loops in it. This type of flowcharting is called top-down or flow-through flowcharting. The advantage of flowcharting is that if you can flowchart your application, then you will be able to script it, no matter how complex. Also, the flowchart does not need to be overly complex or detailed; it is simply your roadmap, or plan, to keep you on the right track.

Initial Script Operation

After you flowchart your application, the next step is to decide which scripts will control each process in your flow chart. If there are no timed or scanned scripts (that is, While True, While Showing, and so on), when WindowViewer starts up, the script engine will execute the scripts in the order shown in Table 1.

Table 1. InTouch Script Engine Order of Execution

1. Application On-Startup
Scripts
10. Open Window(s) While
Showing Scripts
2. Data Change Scripts 11. Data Change Scripts
3. Condition Scripts 12. Condition Scripts
4. Home Window(s)
On-Show Scripts
13. Windows On-Close Scripts
5. Data Change Scripts 14. Data Change Scripts
6. Condition Scripts 15. Condition Scripts
7. Application
While-Running Scripts
16. Application On-Shutdown
Scripts
8. Data Change Scripts 17. Data Change Scripts
9. Condition Scripts 18. Condition Scripts

Figures 1 and 2 below comprise a simplified flowchart of how the script engine operates that is accurate for all scripting questions that you may have. However, note that the interrupt vector paths are not shown and they may occur at any point in any script. Keep in mind that whenever a timer completes (each timer is checked for completion just after the Tick Interval is reset), the flowchart will branch back to the script subroutine instance which called the interrupt and complete or halt on another timer, then return.

Figure 1. Scripting Flowchart – Main Program Body (Note: AppTick is the Application Tick Interval)

Figure 2. Scripting Flowchart – Script Subroutine

The unscanned Application On Startup script is run first. Data Change or Condition scripts may not execute from an Application On Startup script.

Warning If you try to execute a Data Change or Condition script from an Application On Startup script, then the data that you are changing may not yet be available globally. This is because the InTouch runtime variable database is initializing while the Application On Startup script is executing. Technical Support’s tests show that in some cases, a Data Change or Condition script may actually run, however, this may not be true every time Window Viewer is restarted.

If a window is called from an Application On Startup script, then the window’s processes (including any Window Action scripts that are called) will not start until the Application On Startup script completes. However, these requests will be queued and run once the Application On Startup script and the home window’s On Show script complete.

The home window’s Window Action On Show scripts run after WindowViewer successfully starts up. If these scripts change any data, then any unscanned Data Change scripts are executed first, and the unscanned Condition scripts are executed next. All scanned scripts are handled in this same manner.

The difference between the unscanned and scanned scripts is that the scanned scripts are put into a storage area during the scan time, and the remaining unscanned scripts within the scanned script shell or thread will not run until the script scan time completes. (Note that this type of script design allows “nesting” of scripts operating within other scripts.) Once the scan time expires, this causes an interrupt vector in the current script. The interrupt branches to the timed out scanned script which runs either to completion or until another scanned script executes.

Timed out scripts do not run when the script timer completes. Remember that many processes are running at any given moment, and some of these processes cannot be interrupted. Examples of processes that cannot be interrupted are disk writes, DDE updates, ODBC, and preconditioned processes in InTouch (that is, FOR-NEXT loops, other scripts with senior precedence, and so on). When the scan time expires, a flag that prevents the script from running while the timer is counting is cleared, allowing the timed script to begin. A script with a scan time of 100 milliseconds would probably run once every 100 milliseconds if there was no I/O Server running or historical logging or retrieval, and if the application had only one simple window with no other scripts running. However, this is unrealistic for “real world” applications!

On Shutdown Application scripts run when WindowViewer is shutting down. If you try to execute a Data Change script and/or a Condition script from an On Shutdown script, then the Data Change and Condition scripts may not be called or complete. Like the On Startup scripts, the Data Change and Condition script subroutines in the script engine may not be available during shutdown. If you are trying to achieve some internal process or condition before WindowViewer exits, your best chance of achieving that process or condition is to execute the Data Change or Condition script before the On Shutdown script. When the On Shutdown script is running, processes within WindowViewer are being shut down. Under certain circumstances, “long” processes will not finish if WindowViewer shuts down before the task completes that were executed from the On Shutdown script.

Tick Interval and Script Timing

The Tick Interval is configured in WindowMaker under the menus Special/Configure/View Generic/Tick Interval. This setting is the master application tick for all running scripts. If you have a Tick Interval of 1000 milliseconds and your timed scripts running within the script engine are set for 100 milliseconds, then they will not run at least until the Tick Interval has been reset. The result is that each timed script will not run for at least 1000 milliseconds even if they are set for a smaller value. Note that these times are not cumulative. That is, if you use a timed script, the timer will run asynchronously with the Tick Interval timer.

What happens if the Tick Interval is set for a smaller value than your timed script? For example, if the Tick Interval is set to 100 milliseconds and a Condition script set to 450 milliseconds, then when will the Condition script run? Assuming no “long” processes are running that take more than a few milliseconds, once the Condition script begins and the timer is running, the Tick Interval will reset five times before the Condition script times out. This means the script will run at about 500 milliseconds, not 450 milliseconds.

Within the InTouch application, the “outside” loop of the script engine (as shown in Figure 1) has the lowest priority. This is so other Windows processes can continue to run. These Windows processes will try to run at 55 milliseconds under Windows 95 or Windows for Workgroups, or 10 milliseconds under Windows NT; this is the OpSysTick. DDE processes are serviced at this rate, then are redefined at the scan time set in the I/O Server, if one is running. The “operating system” screen updates are handled at this rate, as well as the keyboard and mouse “operating system” scans.

Invoked Immediate Scripts *

(* “Immediate” is a programming term that is used to describe the current or immediate program process thread.)

An Invoked Immediate script is a script that is called from any process that is currently in focus. This does not necessarily depend on the Tick Interval or the main script engine thread. Two examples of an Invoked Immediate script are: 1) calling a Data Change script that is triggered by a DDE update (that is, a I/O Server updates a value in the InTouch runtime database); and 2) running a Pushbutton or Key script. These Data Change, Pushbutton, and Key scripts run immediately until they complete. Note that all other processes are halted until these scripts complete or until they start a timer (which allows for an interrupt vector) so that InTouch can branch to other processes.

An interesting effect is how Immediate windows are opened. If, for instance, a Pushbutton script calls a popup or overlay window whose Window Action script then calls another popup or overlay window, then in what order are the scripts executed? The Pushbutton script will run the script subroutine shown in Figure 2 which will run a Show() window function that is a line in the Pushbutton script. Show() then calls the popup or overlay window which starts its On Show Window Action script. This script will attempt to call a second popup or overlay window; however this will not occur until the first On Show Window Action script completes. A script cannot call itself, even if it is in a different window. The purpose is to prevent infinite loops. However, future versions of InTouch may not behave in this manner.

Test Application

Two versions of an InTouch test application was created to demonstrate how the script engine works.

Note Both test applications are available on the Wonderware BBS (phone 949-727-0726).

This application does the following:

  1. Successive scripts were defined, starting with the outermost script shell and progressing inward, including paths for the interrupt vectors.
  2. Each successive script updates a new tag with a counter. Once each tag is updated, the counter will increment. This defines a specific operation path for the script engine.
  3. Different script types are tried in various orders to show how the script engine operates and to predict what the script engine will do so that a flowchart of the script sequence is created.

The following lists the scripts that were written for our InTouch test application.

Window Scripts for “Test Scripts”:
Script on Show:
g = startupvar;
startupvar = startupvar + 1;
i = startupvar;
startupvar = startupvar + 1;
k = startupvar;
startupvar = startupvar + 1;
l = startupvar;
Application Script:

On Application Startup:
testvar = 1;
startupvar = 1;
A = startupvar;
startupvar = startupvar + 1;

While application running, every 100msec:
IF testvar THEN
startupvar = startupvar + 1;
b = startupvar;
startupvar = startupvar + 1;
d = startupvar;
startupvar = startupvar + 1;
f = startupvar;
startupvar = startupvar + 1;
testvar = 0;
ENDIF;

Condition Script:
Condition:
b > 0
Comment:

On True:
startupvar = startupvar + 1;
c = startupvar;

Condition Script:
Condition:
g > 0

On True:
startupvar = startupvar + 1;
o = startupvar;
Data change script:
On Changes to b:
startupvar = startupvar + 1;
e = startupvar;

Data change script:
On Changes to g:
startupvar = startupvar + 1;
j = startupvar;

Data change script:
On Changes to j:
startupvar = startupvar + 1;
m = startupvar;

Comment:

On True:
startupvar = startupvar + 1;
h = startupvar;

Condition Script:
Condition:
j > 0
Comment:

On True:
startupvar = startupvar + 1;
n = startupvar;

Condition Script:
Condition:
p > 0
Comment:

On True:
startupvar = startupvar + 1;
q = startupvar;
Condition Script:
Condition:
A > 0
Comment:

On True:
startupvar = startupvar + 1;
s = startupvar;
Condition Script:
Condition:
r > 0
Comment:

On True:
startupvar = startupvar + 1;
End1 = startupvar;

Condition Script:
Condition:
n > 0
Comment:

Data change script:
On Changes to m:
startupvar = startupvar + 1;
p = startupvar;

Data change script:
On Changes to o:
startupvar = startupvar + 1;
r = startupvar;

Data change script:
On Changes to s:
startupvar = startupvar + 1;
t = startupvar;

Data change script:
On Changes to q:
startupvar = startupvar + 1;
End2 = startupvar;

The application window shown in Figure 4 was developed based on the scripts shown on the previous page. The values displayed on the window are from ‘startupvar’ which was initialized in the On Startup Application script and is incremented each time a new tag is updated with the new value. These are the script thread values which show the path that the script engine “travels” through all the scripts. The letters preceding the thread values are the actual tagnames which you can reference in the listed scripts. Notice that the scripts demonstrate the script engine’s order of execution that is shown in Table 1.

Figure 4. InTouch “Test Scripts” Application Window

By changing the Condition script which initiates tag ‘o’ to a scanned While True Condition script with a scan time of 1100 milliseconds, an interrupt vector will be generated from a script “holding area” when the timer expires. The result is that the Data Change and Condition scripts in its branch will not start as shown in Figure 5.

Figure 5. Test Application Window with the Modified Condition Script

For our test application, the scan time was set to 1100 milliseconds. This value was chosen because it illustrates the Condition script timer expiring and the halted processes resuming. Notice where the interrupt vector appears in the timed script. If this same application were to run on a different computer, the processes running on each computer might be different enough to cause the interrupt vector to appear in another location. Also, the Tick Interval will not affect where the interrupt vector will appear. (The test application was run using a 100 milliseconds Tick Interval and a 100 milliseconds system tag update time.)

If the Tick Interval was changed to 20000 milliseconds as shown in the TESTSCR2 application in Figure 6, then the scripts will run exactly the same, except that the next iteration of the application loop (which is controlled by the Tick Interval) will run only after the Tick Interval is reset. This occurs after the “n o” Condition script has run. This shows an interrupt vector “node” or a place where the script engine was interrupted to handle other processes based on some decision that probably deals with an external process time or ‘wait’ period. Although this particular interrupt location cannot be easily predicted, it does provide an insight on when DDE and other processes might be updated.

A common question is “When are DDE tags updated?” Based on our test application, in most instances, DDE tags will not be updated until the Tick Interval is reset. But why is this? In order for DDE tags to be updated, or be active, one of the following ten conditions must occur:

  1. A DDE topic is set to Advise All Items.
  2. A tagname is displayed in an open application window.
  3. A tagname is used in a Window script or Action script and the application window that is associated with either script is opened.
  4. A tagname is actively being used by a real-time trend.
  5. A tagname is used for alarm purposes.
  6. A tagname is event logged and Event Logging is enabled.
  7. A tagname is being logged in an Historical Log file and Historical Logging is enabled.
  8. A tagname is used in a Key, Condition, Data Change, or Application script.
  9. A tagname is an Auto Collection tagname in the SPC Program.
  10. A tagname is currently accessed by a client application (such as Microsoft Excel) using DDE.

Except for item 1, the tagname in each of the nine remaining items has some link to a script or an application window (which has a link to a script). Since we know when the DDE tag is updated, we can assume that the tag under these conditions will be updated at approximately the Tick Interval. Item 1 is based on the I/O Server, so the update time is equal to the I/O Server’s scan time (which is set in the I/O Server or topic—it has nothing to do with the script engine). When a DDE item is written by a user input, such as pressing the <Enter> key, it will cause an interrupt vector. The interrupt vector makes a request to the server to write the value to the DDE device at the DDE server’s tick time.

Updates from the DDE device will not appear immediately if it is routed through the script engine.

As an example, create the following items in a new application:

  • A DDE User Input tag which is a hot link to an Microsoft Excel spreadsheet;
  • A separate value display using the DDE tag as the expression;
  • A display for a tag value being updated from a DDE tag through an immediate Data Change script (this runs as an instance of the variable database being changed by DDE);
  • A display for a tag value being updated from a DDE tag through an immediate, unscanned Condition script (this runs as an instance of the variable database being changed by DDE).

Then, show the Excel spreadsheet on the monitor screen underneath the InTouch windows. By setting the Tick Interval to 20000 milliseconds, the application shows that as the User Input tag value is changed, the Excel spreadsheet, the DDE tag value, and the rewritten tags are all immediately updated at the conclusion of the interrupt vector and displayed to the screen, regardless of what the Tick Interval value. (This could be a Pushbutton Action script instead of a user input.)

Choosing the appropriate scan time/Tick Interval for these scripts may require tuning in that you may need to try several values until a satisfactory value can be found. The reason for this is that there are many other processes running within InTouch that need to be serviced, in addition to the script engine. Some of these processes are DDE accesses, screen updates, and checking for messages for the WW Logger. Each of these services require some system overhead time, and depending on how complex your application is, the appropriate scan time/Tick Interval will vary for each application. Note that while within the script engine, some external processes may not be updated. Be very careful when you make assumptions about external processes such as updating DDE tagnames. The simplest thing to do is to make your scripting as streamlined as possible and to avoid unnecessary coding or loops which can consume system overhead time.

Conclusion

There are many factors which affect the InTouch script engine. If you are not careful when designing the scripts for an application, your application may result in an undesired behavior. To avoid problems with complex scripts, you should graphically display what you want to accomplish in your scripts. This can be done by flowcharting your application before you start to write your scripts. Also, optimizing your application may require proper nesting of scripts and adjusting the scan times.

Appendix A: Some Scripting Related Questions and Answers

Q How are scripts scheduled for execution in an InTouch application?

A All scripts are event driven. Events may be a data change , a condition, a timer, and so on. The order that scripts are executed is different for each application. Thus, there is no guaranteed order of execution. Scripts execute in the order that their associated triggering events have occurred. This means that two events cannot happen at the same time under Windows; every event has a unique time stamp. Currently, the order of execution for scripts is based on event time stamps and nothing else. If a tag is defined as retentive and is modified in a script, then the file I/O is performed when its value is changed. Normally, there are no peeks while the script is executing. Any script that brings up a dialog or selection box will peek to allow the processing of the Windows messages (that is, DDE input is processed, keystrokes are processed, time initiated scripts are processed, and so on). This means that other scripts may be initiated while the dialog or selection box is displayed. In this case, the dialog or selection box does not regain control until the scripts that were initiated are completed.

A Data Change script may act like a subroutine within a script. If the value of a tag, which is linked to a Data Change script, changes while another script is executing, the script that is currently running will pause. The Data Change script will then execute and complete, then the other script will then resume executing. Similarly, if a line in a Data Change script changes the value of a tag that is tied to second Data Change script, the first Data Change script will pause, the second Data Change script will execute, then the first Data Change script will resume executing.

Data Change scripts run only when a tag value is updated. If the tag value comes from DDE, then the Data Change script executes once the DDE value is received. If the tag value is changed by another script, then the Data Change script will immediately run and complete before InTouch will execute the next line in the script. Note that this could cause an infinite loop. To prevent this from happening, do not allow a script to execute if it is still active.

Here are two examples of how to prevent an infinite loop in a script:

Script1 calls Script2 which calls Script3 which attempts to call Script2. In this case, the last attempt to call Script2 will not execute.

Data Change script on Tag1 which modifies Tag2. Data Change script on Tag2. Script1 modifies Tag1.

Q What is the sequence and timing for executing commands within a script?

A Each command in a script is executed in the order that it is found in the script file. Each command is completed before it moves to the next command, except for functions that require a DONE Tag such as FileMove(), FileCopy() or PrintWindow().

The following lists the order of precedence, in descending order, for evaluation of script operators. Operators that are listed in the same line have equal precedence.

( ) Ü Highest Precedence
– , NOT, ~
**
* , /, MOD
+, –
SHL, SHR
<, >, <=, > =
==, <>
&
^
|
=
AND
OR Ü Lowest Precedence

Q What are the effects of blank and comment characters in a script?

A Blank and comment characters are ignored. When the left brace ({) is encountered, the script engine continues ignore the characters until a right brace (}) is encountered. This may be used in any InTouch script or expression box. Its effect on the timing of the script is negligible. Wonderware Technical Support recommends that you document your scripts and expressions with comment characters.

Q How do scripts interact? What is predictable and what is not?

A If one script is currently running and a second script is triggered, then the first script is halted and the second script executes to completion. Any tagnames that are changed by the second script will be seen by the first script. If a tag value is changed, then the message is changed immediately, but it will not be processed by the receiving program (that is, a I/O Server) until at least at the end of the script. When the DDE server gets the processor, it will do the write on its next message for that particular topic.

Q How can I use a script as a subroutine?

A Data Change scripts can be used as subroutines for other scripts. That is, if the Data Change script is started from another script, InTouch will branch out and run the Data Change script as a subroutine.

For example, say you have a Data Change script based on a tag called Trigger and the script uses “value = value + 10;”. Then, you can create a Pushbutton or a Condition script with these lines:

trigger = not trigger;
trigger = not trigger;
trigger = not trigger;
trigger = not trigger;

When this script runs once, the Data Change script on Trigger runs each time “trigger = not trigger” was interpreted while it was still processing the first script. This technique allows you to set up subroutines that can be triggered from inside of other scripts. This can be extremely powerful!

However, a change in a tag value should not be used to call a previously triggered script (that is, if Script1 calls Script2 which calls Script3 which attempts to call Script1, the final call will not be executed). That is, tagnames that are modified in a Condition script or a Data Change script should not be used as the tagname for a Data Change script or in the expression of a Condition script.

Example:

A Data Change script that executes based on the value of tag “A”, contains the line “B=B+1.” Tagname “B” should not be used as the tagname for a Data Change script or be part of the expression for a Condition script.

You can also “nest” your scripts (that is, have a script call another script which calls another script, and so on). But, the maximum number of nested levels for script execution depends on the size of the window stack which is represented by the Stack parameter value in your SYSTEM.INI file. (During installation, InTouch ensures that the Stack parameter is set to a value that is adequate for most scripting situations.)

Q Can I modify the value of a tag that is linked to a Data Change script which is within the body of the same script? What about modifying tag values that are linked to a Condition script?

A If the tagname is linked to a Data Change script (that is, it is listed in the Tagname field), and the tag’s value is changed within the body of that same script, then it will modify the value once. For example, if the tagname MYTAG is linked to a Data Change script that contains the line “MYTAG = MYTAG + 1”, then the script will increase the value of MYTAG by one and exit. The Data Change script will not execute again. This feature prevents infinite loops. If the MYTAG value is redefined several times in the Data Change script, then each redefinition will take place, but the Data Change script will not execute again.

Warning Do not write any scripting which relies on this behavior. Future versions of InTouch may not operate following this logic and it will expose your application to upgrading difficulties and/or incompatibilities.

If you modify the value of a tag that is linked to a Condition script, then within the body of that same script, the results may not be what you expect. The following is an example of what happens when you do this.

Here is an example Condition Script:

Condition: ( X == 25 )
ON TRUE body:
PrintWindow(“Main Window”);
Blob = TAN(MyAngle);
X=0;
AppActivate(“NotePad”);
Show(“Blaster Control”);
TagLevel = NewValue * SIN( Blob );
ON FALSE body:
SendKeys(“Main Window Printed”);
Blob = 0;

You would think that execution would proceed as follows:

PrintWindow(“Main Window”);
Blob = TAN(MyAngle);
X=0;
AppActivate(“NotePad”);
Show(“Blaster Control”);
TagLevel = NewValue * SIN( Blob );
SendKeys(“Main Window Printed”);
Blob = 0;

That would make sense; the ON-TRUE script executes first, then the ON-FALSE. But what really happens is this:

PrintWindow(“Main Window”);
Blob = TAN(MyAngle);
X=0;
[ Pause the ON-TRUE ]
[ Launch ON-FALSE ]
SendKeys(“Main Window Printed”);
Blob = 0;
[ Resume ON-TRUE ]
AppActivate(“NotePad”);
Show(“Blaster Control”);
TagLevel = NewValue * SIN( Blob );

Now the value of Blob has been reset to zero (at the wrong time), and more importantly, the SendKeys has failed to make it to Notepad, since it was not active yet.

Q If a tag is defined as retentive and its value changes in a script, then is the file I/O performed immediately after the value changes?

A No, not until the script has finished executing.

Q Is it true that if a tag value changes within a script, then any Data Change scripts will immediately execute? What about Condition scripts set to On True or On False—will these types of Condition scripts immediately execute that are affected by the new tag value?

A Yes for both questions. Be aware that this feature may change in a future InTouch version. In general, you should not rely on the Data Change scripts or the Condition scripts executing immediately after the tag value changes. Instead, you should design your system to avoid this type of condition from happening. This way, your application will not be adversely affected when you upgrade to a future version of InTouch.

Q Does a script need to run to completion before it can give up the CPU? At what point in the script can I do a PeekMessage to give other applications a chance to run? Also, if a script triggers or executes other scripts, when does the CPU get released?

A The script engine will capture the CPU during script execution. At no time during the execution of a script will the CPU be released. PeekMessage( ), which is an Windows API call, is not performed while the script executes.

Q Is there an upper limit to the nesting level for executing scripts? How many scripts can be chained together to execute in a series through a Data Change script?

A Wonderware Technical Support is not aware of an upper limit on how many scripts you can nest or how many scripts you can chain together. Be aware that the practice of purposely chaining scripts together is not a good idea because there may be incompatibility issues with future versions of InTouch.

Q If a tag value changes, then is the new value immediately sent to the I/O Server? If not, when? When does the I/O Server perform the write? Is a I/O Server inactive while the script executes?

A No, the new tag value is not immediately sent to the I/O Server. Instead, the value is sent after the script completes. And, yes, the I/O Server is temporarily inactive while a script executes.

Q When are the system tags for date and time updated? (that is, $Month, $Day, $Year, $Time and so on) I thought they were updated based on the value of the Update Time Variables setting under /Special/Configure/View Generic. I wrote a script to change the time and date, and $Time changed, but $Date did not update until WindowViewer was restarted.

A If you change the system time or date on your computer, then be sure to send a WM_TIMECHANGE message to all Windows applications that are currently running, including your InTouch applications. Windows applications rarely “poll” for the current time.

Q I want to print a file from my InTouch application. How can I do this?

A You can use the FileCopy()function, as in this example:

status = FileCopy(“c:\autoexec.bat”,”lpt2″, Monitor.Name);

This prints the AUTOEXEC.BAT file on printer LPT2 and uses the Integer tag Monitor as the DoneTag. (Note: You can also use the FilePrint() function that is part of the Technical Support script function library which is available on the  Knowledge Base CD.)

Q How do I create a timer in InTouch?

A Use a Condition script that references a Memory Discrete tag named Flag. Then, create an On True Condition script that references a tag named Counter that is set to zero (that is, initialize the counter). Set the time, While True Every xxx msec, to the desired frequency. The While True Condition script should increment the Counter tag every time the script runs. When Counter is greater than a preset value, set a Memory Discrete tag called Trigger to one (1).

Here is an example Condition Script:

Counter = Counter + 1;

IF Counter >= 5 THEN
Trigger = 1;
ENDIF;

Q How do I toggle a Discrete tag from a script?

A Try the following:

Discrete = 1 – Discrete;

or

Discrete = NOT( Discrete );

Q I am using the On Shutdown Application script to kill the applications ‘App1’ and ‘App2’ when my InTouch application exits (by choosing Exit from the File menu). Here is my On Shutdown Application script:

ActivateApp “App1”;
SendKeys( “%(f)” );
SendKeys( “x” );
ActivateApp “App2”;
SendKeys( “%({F4})” );

However, when I exit my application, ‘App1’ and ‘App2’ are still running. I copied this script into a Pushbutton Action script and the two applications were killed. Why does my On Shutdown Application script not work?

A Because WindowViewer captures the CPU during shutdown, you cannot run a script which would cause another application to get access to the CPU. Thus, the ActivateApp( ) function will not work in an On Shutdown Application script.

Q Then, why is there no KillApp( ) script function?

A There is a script function called WWControl( ). WWControl( ) can be used to terminate an application. If you use it in your Application Action script, then it will kill your applications during shutdown. For example, insert this line into an On Shutdown Application script:

WWControl( “Notepad – (Untitled)”, “CLOSE”);

Run Notepad without loading any files and then start up the application under WindowViewer. Exit WindowViewer and the Notepad application should disappear.

Appendix B: Indepth Review of Complex Script Functions

The InTouch script editor supports two “styles” of scripts: Simple and Complex. Simple scripts allow you to do assignments, comparisons, simple math functions, and so on. Complex scripts allow you to perform logical IF-THEN-ELSE type statements and to process loops using the FOR-NEXT script structure. In addition, InTouch also supports the use of built-in complex script functions, such as StartApp().

Functions with the argument ApplicationName will start the Windows application identified in the ApplicationName argument. These type of functions may be used in both simple and complex scripts.

Note that each IF statement requires an ENDIF statement. Also be aware that an ELSE statement is not required if your script does not need it.

The first NEXT closes the inner FOR loop and the last NEXT closes the outer FOR loop. Likewise, in nested IF statements, the ENDIF statements automatically apply to the nearest prior IF statement.

The following is an example of an IF-THEN-ELSE script:

IF React_temp > 200 THEN
React_temp_sp = 150
PRValve = 1
PlaySound (“c:\fire.wav”,1);
ELSE PRValve =0;
PlaySound (“c:\All_Ok.wav”, 1);
ENDIF;

In this example, the script checks if React_temp is greater than 200. If so, then Reactor_temp_sp is assigned the value of 150, PRValve is turned on and the FIRE.WAV file is played. If React_temp is equal to or less than 200, then the PRValve is turned off and the ALL_OK.WAV file is played. Note the use of the PlaySound(path_text,number) in this script.

Here is an example of a FOR-NEXT loop script. This loop performs a simple iterative mathematical calculation. When executed, Product equals the value of NumberToRaise raised to the power of 10 (that is, Product=NumberToRaise10).

Product = 1;
NumberToRaise = 4;
FOR Index = 1 TO 10
Product = Product * NumberToRaise;
NEXT;

Once the above script has completed processing, the value of the Product will be 1,048,576.

Here are some more examples of various complex scripts:

IF-THEN statement with no ELSE clause:

IF a <> 0 THEN
a = a + 100;
ENDIF;

IF-THEN-ELSE statement with one ELSE clause:

IF temp > 500 THEN
Disc = 1;
Real = 43.7;
ELSE
Disc = 0;
Real = 93.4;
ENDIF;

IF-THEN-ELSE statement with one ELSE IF clause and no ELSE clause:

IF temp > 500 THEN
Disc = Disc * 10;
ELSE
IF temp > 250 THEN
x = y / z;
a = abc + def;
ENDIF;
ENDIF;

IF-THEN-ELSE statement with one ELSE IF clause and one ELSE clause:

IF temp > 500 THEN
Disc = Disc – 10;
ELSE
IF temp < 250 THEN
Disc = Disc + 10;
ELSE
Disc = Disc + 50;
Real = 100;
ENDIF;
ENDIF;

IF-THEN-ELSE statement with multiple ELSE IF clauses and one ELSE clause:

IF temp > 100 THEN
temphihi = 1
Disc = 50;
ELSE
IF temp > 80 THEN
temphi = 1;
ELSE
IF temp < 30 THEN
templo = 1;
ELSE
IF temp < 10 THEN
templolo = 1;
ELSE
tempok = l;
ENDIF;
ENDIF;
ENDIF;
ENDIF;

IF-THEN-ELSE statement that tests for Condition 1 or Condition 2:

IF (pump1 < 50.0) OR (pump2 < 50.0) THEN
alarm-1 = 1;
ELSE
alarm-1 = 0;
ENDIF

IF-THEN-ELSE statement that tests for Condition 1 and Condition 2:

IF (pump1 < 50.0) AND (pump2 < 50.0) THEN
alarm-2 = 1;
ELSE
alarm-2 = 0;
ENDIF;

IF-THEN-ELSE statement that tests for equivalency:

IF a > 50 THEN
IF b == 100 THEN
c = 0;
ENDIF;
ENDIF;

Control structures can be placed inside other control structures (such as an IF-THEN block within a FOR-NEXT loop). A control structure inside another control structure is known as nesting. Example:

FOR TagX = 1 TO 5
FOR TagY = 1 TO 10
…statements…
IF (condition) THEN
[EXIT FOR;]
ENDIF;
…statements…
NEXT;
NEXT;

Where:

The first NEXT closes the inner FOR loop and the last NEXT closes the outer FOR loop. Likewise, in nested IF statements, the ENDIF statements automatically apply to the nearest prior IF statement.

Leave a Reply

Your email address will not be published. Required fields are marked *

12 − = 3