12.5. Common: The Text Message Display - read_msg and messages.txt

The messages displayed in the Controller's right-hand text box come from a single text file (messages.txt, shown below). The read_msg function (located in lib/common.g) is responsible for finding the requested message and inserting it into the text box.

   /*--------------------------------------------------------------------
    * Function:    all_white
    * Returns:     t or nil
    * Description: Determines whether a line contains only a blank space
    *              or tab characters.
    *------------------------------------------------------------------*/
   function all_white(line)
   {
     local i, len=strlen(line), white=t;
     for (i=0; i<len && white; i++)
       if (line[i] != ' ' && line[i] != '\t')
         white=nil;
     white;
   }

The read_msg uses the all_white function to identify lines with just white space or tabs.

   /*--------------------------------------------------------------------
    * Function:    read_msg
    * Returns:     A string
    * Description: Finds a message in the messages.txt file, reads each 
    *              line, and returns the whole message as a single string.
    *              Uses the all_white function to create new lines.
    *------------------------------------------------------------------*/
   function read_msg(msgno)
   {
     local fp, marker, msg = "", line = nil, white;
     
     fp = open("messages.txt", "r", nil);
     while(line != _eof_)
     {
       line = read_line(fp);
       marker = string("#", msgno);

The read_msg function opens the messages.txt file for reading using the Gamma open function. The while statement used with the Gamma read_line function lets us read the file line by line.

We find the line we need by looking for the marker "#msgno", where msgno is the message number parameter passed to the function as a string. The marker is constructed using the Gamma string function. The Gamma strstr function is used for making the comparison.

       if ((strstr(line, marker)) == 0)
         {
           line = read_line(fp);
           msg = "";
           while(line != "#END")
             {
               white = all_white(line);
               msg = string(msg, white ? "" : " ", line, white ? "\n" : "");
               line = read_line(fp);
             }
           line = _eof_;
         }
     }
     close(fp);
     msg;
   }
   

Once we get to the message, we read past one blank line, read the first line of the message, and then enter a second while loop. Inside this loop we use the string function again to join each new line of the message to the previous lines, constructing one long string. Our string function arguments use a ternary operator to resolve the value of the white variable. When we get to a line containing #END, we leave both while loops, use the close function to close the file, and return the message string (msg).

The messages.txt file

The messages.txt file contains all the messages that appear in the Controller. Each message is marked by #number at the start of the title line, and #END at the end of the message, which are detected by the read_msg function. The extra line between each of these markers and the body of the message allows the text editor to reformat each message paragraph without disturbing the other lines of the file.

#1 Controller

          Welcome to the
	  
       Cogent Tools Demo.

       
   This is the Controller, a Gamma program that controls the other
programs in the demo.  It automatically starts the Cascade NameServer
and Cascade QueueServerfor interprocess communication (IPC); and then
it starts the Cascade DataHub to handle rapid data transfer.

   Each program started is independent, communicating with the others
via IPC.  You can press the PID Emulator button to begin.

#END
#1.1 Process Status Text Box

Note: Not in use-- needs "enter" and "leave" signals for a text box.
This is the status of every Cogent process that is currently running
on your system.  The information is generated by the Cascade NameServer.


   The normal view is an edited version of the Cascade NameServer
output, created by the Controller program.  To view the unedited
information, use the "Raw output" button.

#END
#2 PID Emulator

               PID Emulator

   
The PID Emulator is a Gamma program (emul.g) that runs behind the
scenes, generating data to emulate a PID loop.  

   Every 1/10 second it generates data for the variables SP (set
point), MV (control output), and PV (process variable), and sends the
data to the Cascade DataHub.  From there the data gets distributed to
the other programs in the Demo.

#END
#3 Monitor

                     Monitor

		     
   The Monitor is a Gamma program (monitor.g) that monitors and
controls the PID Emulator.

   From the Monitor you can adjust the PID Emulator, and get a visual
representation of the SP, MV, and PV values.

   All values shown and all adjustments made from the Monitor are
exchanged with the PID Emulator via the Cascade DataHub.

#END
#3.1 Monitor Auto On/Off button

                     Monitor


   The 'Auto mode' button toggles the value of the Cascade
DataHub point AUTO_001 between 0 (OFF) and 1 (ON).

   The PID Emulator is registered for the point AUTO_001, and when its
value changes to 1, the PID Emulator sets an "every" timer.  This
changes the value of SP every FREQ seconds (as set by the FREQ spin
button).

   When the button clicked OFF, the value of AUTO_001 changes to 0,
and the "every" timer gets cancelled.

#END
#3.1a SP slider

                     Monitor


   The 'SP: Set Point' slider lets you change the set point in the
demo.  

   This slider is also activated automatically by a timer with a built-in
delay.  You can start and stop the automatic reset by pressing the
'Auto mode' button.  You can set the timer delay using the 'Delay'
spin button.

#END
#3.2 FREQ of change spin button

                     Monitor


   The 'Delay' spin button sets the value of FREQ_001 in the
Cascade DataHub.

   The PID Emulator is registered for the point
FREQ_001, and when that value changes, the PID Emulator resets
frequency of the "every" timer to the new value.

   The new value becomes the new rate of change (in seconds) of SP
when the automatic mode is ON.

#END
#3.3 Kp: Proportional spin button

                     Monitor


   The 'Kp: Prop' spin button sets the proportional value PID1_Kp
in the Cascade DataHub.  This value is a proportion applied to the
difference (or error) between the set point (SP) and the process
variable (PV).

   The PID Emulator is registered for the point
PID1_Kp, and when that value changes, the PID Emulator uses the new
value.

#END
#3.4 Ki: Integral spin button

                     Monitor


   The 'Ki: Int' spin button sets the integral value PID1_Ki in the
Cascade DataHub.  This value influences the rate of change of the
control output (MV).

   The PID Emulator is registered for the point PID1_Ki, and when that
value changes, the PID Emulator uses the new value.

#END
#3.5 Kd: Derivative spin button

                     Monitor


   The 'Kd: Deriv' spin button sets the derivative value PID1_Kd in
the Cascade DataHub.  This value inhibits rapid changes, reducing the
amount of overshoot.

   The PID Emulator is registered for the point
PID1_Kd, and when that value changes, the PID Emulator uses the new
value.

#END
#3.6 PROP: Proportional spin button

                     Monitor


   The 'PROP: Proportional' spin button controls the proportion of PV:MV
by setting the value of PROP_001 in the Cascade DataHub.

   The PID Emulator is registered for the point PROP_001, and when
that value changes, the PID Emulator uses the new value.

#END
#3.7 INT: Integral spin button

                     Monitor


   The 'INT: Integral' spin button controls the damping effect on PV by
setting the value of INT_001 in the Cascade DataHub.

   The PID
Emulator is registered for the point INT_001, and when that value
changes, the PID Emulator uses the new value.

#END
#3.8 Good radio button

                     Monitor


   The 'Good' button resets all the MV and PV spin buttons to set
up an optimally performing PID loop.  The new values are sent to the
Cascade DataHub, which sends them along to the PID Emulator.

   Also, the FREQ spin button is set to 4 to get a higher rate of
change in automatic mode, because the PV value in a Good PID loop
generally stabilizes in about 1 second.

#END
#3.9 Poor radio button

                     Monitor


   The 'Poor' button resets all the MV and PV spin buttons to set
up a poorly performing PID loop.  The new values are sent to the
Cascade DataHub, which sends them along to the PID Emulator.

   Also, the FREQ spin button is set to 10 to get a low rate of change
in automatic mode, because the PV value in a Poor PID loop might not
stabilize for 8 or 9 seconds.

#END
#3.10 Oscillating radio button

                     Monitor


   The 'Oscillating' button resets all the MV and PV spin buttons to set
up an oscillating PID loop.  The new values are sent to the Cascade
DataHub, which sends them along to the PID Emulator.

   The Automatic mode button is set to OFF, since automatic mode is
not necessary here.

#END
#3.11 Out-of-control radio button

                     Monitor


   The 'Out-of-control' button resets all the MV and PV spin buttons to
set up a PID loop with ever-increasing values.  The new values are
sent to the Cascade DataHub, which sends them along to the PID
Emulator.

   The Automatic mode button is set to OFF, since automatic
mode is not necessary here.

#END
#4 DataHub Viewer

             DataHub Viewer

	     
   The DataHub Viewer is a Cogent utility (xdhview in GTK, phdhview in
Photon) that gives you a window into the Cascade DataHub.

   Each data point is listed by name, and all of its attributes, such
as value, confidence, and the date and time the point was last
updated, are shown.

   From the DataHub Viewer you can select any point and manually
change its attributes.

#END
#5 Log

                      Log


   Log is a Gamma program (log.g) that demonstrates the Cascade
TextLogger.

   The Cascade TextLogger takes data from the Cascade DataHub and writes
it in ASCII format to a file or STDOUT.  You can control how, when,
and what data gets logged.

   In Linux, Log uses gnuplot to read the Cascade TextLogger files and
generate plots of the data.

#END
#5.1 Any radio button

                      Log


   The 'Any' collect button sends a (collect any) command to the Cascade
TextLogger, causing it to write a new line whenever a logged point's
value changes in the Cascade DataHub.

   Only the new values are written.  Points whose values haven't changed
are marked with an asterisk (*).

   This is the default setting.

#END
#5.2 Fill radio button

                      Log


   The 'Fill' collect button sends a (collect fill) command to the Cascade
TextLogger, causing it to write a new line whenever a logged point's
value changes in the Cascade DataHub.

   Values for all the other
points are filled in, even if they haven't changed.

#END
#5.3 All radio button

                      Log


   The 'All' collect button sends a (collect all) command to the Cascade
TextLogger, causing it to write a new line only when all of the logged
point's values have changed in the Cascade DataHub.

   For example, in
this demo, a line will be written right after SP changes its value,
because all variables will have new values at that time.  The values
for MV and PV change frequently, but no lines are written until SP's
value changes as well.

#END
#5.4 Insert Text button

                      Log


   The 'Insert Text' button sends an (output) command to the Cascade
TextLogger, causing it to write the line of text in the entry box to
the output file.

   You can send any text string you like; the "#"
character is not necessary.  It appears in the example text because it
marks the start of a comment for gnuplot, and when used at the
beginning of the line it prevents creating gaps in the plots.

#END
#5.5 Send Cmd button

                      Log


   The 'Send Cmd' button sends a command of your choice to the Cascade
TextLogger.  Commands are written in Lisp syntax, using parentheses.
The (exit) command is given as an example.

   Please refer to the Cascade TextLogger Manual for a complete list
of commands and documentation on their use and syntax.

#END
#5.6 Log to: button

                      Log


   The 'Log to' button starts the Cascade TextLogger, using the
configuration file tl.cfg, and according to the 'Collect' and 'Log to'
options.

   The file that receives the log is named tloutput.dat.  When the
'Log to' button is unclicked, the contents of tloutput.dat appear in
the text display.

#END
#5.7 file check button

                      Log


   The 'file' button sends (enable) and (disable) commands to the Cascade
TextLogger to control logging to the tloutput.dat file.  The contents
of this file appear in the text display when the 'Log to' button is
unclicked.

#END
#5.8 stdout check button

                      Log


   The 'stdout' button sends (enable) and (disable) commands to the
Cascade TextLogger to control logging to STDOUT.

#END
#5.9 Plot Recent button

                      Log


   The 'Recent' plot button calls gnuplot to create a continuously updated
plot of the last 15 seconds of logged data.  It reads its data from
two special data files: tlold.dat and tlrecent.dat.

   NOTE: To
simulate a trend, we run gnuplot in a loop, creating a new plot every
second.  To close the plot window, you have to untoggle the 'Recent'
button.  Otherwise the window will continue to be redrawn until the
Log program exits.

#END
#5.10 Plot All button

                      Log


   The 'All' plot button calls gnuplot to create a continuously updated plot
of the output.dat file.

   NOTE: Because the data for this plot is ever-increasing, gnuplot
will use progressively more system resources to construct a plot.

   NOTE: To simulate a trend, we run gnuplot in a loop, creating a new
plot every second.  To close the plot window, you have to untoggle the
'All' button.  Otherwise the window will continue to be redrawn until
the Log program exits.

#END
#5.11 Demo message

You can modify the log during run-time like this:


------------Collect------------

Any: logs any new data.

Fill: logs any new data, filling in existing data.

All: logs data only when all values have changed.


Insert Text: Adds a line of text to the log.

(note: the '#' is a comment character for gnuplot.)


Send Cmd: Sends a command to the Cascade TextLogger.

#END
#6 History

                      History


   History is a Gamma program (history.g) that demonstrates the Cascade
Historian's ability to record data and make incisive queries.

#END
#6.2 Record Values

                      History


   The 'Record Values' button enables the Cascade Historian to start
recording data for MV and PV for the number of seconds indicated.


   The data for both of these points will be collected as long
as the PID Emulator is running.

#END
#6.3 Update Display

                      History


   The 'Update display' button sends a query to the Cascade Historian
based on the current Interpolator options.

   The Start time is the number of seconds past midnight last night,
and Duration is the length of the query in seconds.  They are reset
each time time the 'Record' button is used.

   The Time Interval specifies the period for the Periodic and Fixed
Relative interpolators.  Max. gap specifies data gap size where
interpolation is to be suppressed.

#END
#6.31 NoInterpolator

                      History


   The 'NoInterpolator' option lets you run a straight query with no
interpolation.  It plots the Y history (either MV or PV) versus
time.  

#END
#6.32 Periodic

                      History


   The 'Periodic' interpolator option plots the Y history (either MV
or PV) versus time.  

   It is similar to the 'NoInterpolator' option, except you can
specify a time interval and maximum gap for the time axis.

#END
#6.33 Relative

                      History


   The 'Relative' interpolator option plots the Y history (either MV
or PV) versus the X history (also either MV or PV).  

   This interpolator inserts an extra value into the Y history for
each value in the X history.

#END
#6.34 FixedRelative

                      History


   The 'FixedRelative' interpolator option plots the Y history (either
MV or PV) versus the X history (also either MV or PV).

   This interpolator inserts an extra value into the Y history for
each value in the X history.  It is similar to the 'Relative' option,
except you can specify a time interval and maximum gap for the time
axis.

#END
#6.35 Y or X History

                      History


   The 'Y history' and 'X history' entries let you choose the variables
for the Y-axis and X-axis (either MV or PV).

#END
#6.36 Start

                      History


   The 'Start' entry lets you change the start time.  This time
is the number of seconds past midnight.  Whenever you press the
'Record' button, the value entered here changes to the time you
pressed the button.

#END
#6.37 Duration

                      History


   The 'Duration' entry lets you specify how many seconds of the
history you wish to include in your query. Whenever you press the
'Record' button, the value entered here changes to the number of
seconds set in the Record spin button.

#END
#6.38 Time Interval

                      History


   The 'Time Interval' entry is only used in queries with a timed
interpolator (Periodic and FixedRelative).  It sets the interval of
time for the interpolator.

#END
#6.39 Max. gap

                      History


   The 'Max. gap' entry is only used in queries with the Periodic
interpolator.  If the time between two data points exceeds this number
of seconds, then data will not be interpolated between those points.
This is useful if you have large gaps in your data set.

#END
#6.4 Plot Data

                      History


   The 'Plot Data' button calls gnuplot to create a plot of the last
query.  Whenever you make a new query, the plot is automatically
updated.

   NOTE: To support the automatic update feature, we run
gnuplot in a loop, creating a new plot every second.  To close the
plot window, you have to untoggle the Plot Data' button.  Otherwise
the window will continue to be redrawn until the History program
exits.

#END
#6.5 Deadband Types button

                      History


   The 'Set up deadband types' button opens the Deadband Types window,
where you can set the type of deadband on data collected for MV or PV.

#END
#6.51 Deadband: Full data set

                      History


   The 'Full data set' option shows the history that was recorded with
no deadband.  

#END
#6.52 Deadband on, prior off

                      History


   The 'Deadband on, prior value off' shows the history that was
recorded with a standard deadband.

#END
#6.53 Deadband on, prior on

                      History


   The 'Deadband on, prior value on' shows the history that was
recorded with the deadband on, adding for each point displayed the
value that was recorded immediately before.  This can give a more
accurate picture of the data set in certain circumstances.

#END
#6.54 Deadband Types Window

                      History


   The Deadband Types window lets you set the type of deadband on data
collected for MV or PV, to filter out redundant data.

   You can deadband the data itself on an absolute or percent basis,
or both.  And you can set time limits or count limits for when data
gets collected.

#END
#6.55 Cancel

                      History


   The 'Cancel' button reverts the values in the Deadband window back
to what they were the last time the 'OK' button was clicked, and closes
the window.

#END
#6.56 OK

                      History


   The 'OK' button sends the query to the Cascade Historian and closes
the Deadband window.  The values last entered in the window are the ones
sent.

#END