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:    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.
    *------------------------------------------------------------------*/
   function read_msg(msgno)
   {
     local fp, marker, msg = "", line = nil;
     
     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 = read_line(fp);
           while(line != "#END")
             {
               msg = string(msg, " ", line);
               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. 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

\n             Welcome to the\n
       Cogent Tools Demo.\n\n   This is the Controller,
a Gamma program that controls the other programs in the demo.  It
automatically starts the Cascade NameServer and Cascade QueueServer
for interprocess communication (IPC); and then it starts the Cascade
DataHub to handle rapid data transfer.\n\n   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.
\n\n   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

\n               PID Emulator\n\n   
The PID Emulator is a Gamma program (emul.g) that runs behind the
scenes, generating data to emulate a PID loop.  \n\n   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

\n                     Monitor\n\n   The Monitor
is a Gamma program (monitor.g) that monitors and controls
the PID Emulator.\n\n   From the Monitor you can adjust the PID
Emulator, and get a visual representation of the SP, MV,
and PV values.\n\n   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

\n                     Monitor\n
\n   The 'Auto mode' button toggles the value of the Cascade
DataHub point AUTO_001 between 0 (OFF) and 1 (ON).\n\n   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).\n\n   When the
button clicked OFF, the value of AUTO_001 changes to 0, and the
"every" timer gets cancelled.

#END
#3.1a SP slider

\n                     Monitor\n
\n The 'SP: Set Point' slider lets you change the set point in the
demo.  \n\nThis 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

\n                     Monitor\n
\n   The 'Delay' spin button sets the value of FREQ_001 in the
Cascade DataHub.\n\n   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.\n\n   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

\n                     Monitor\n
\n   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).\n\n   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

\n                     Monitor\n
\n   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).\n\n   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

\n                     Monitor\n
\n   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.\n\n   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

\n                     Monitor\n
\n   The 'PROP: Proportional' spin button controls the proportion of PV:MV
by setting the value of PROP_001 in the Cascade DataHub.\n\n   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

\n                     Monitor\n
\n   The 'INT: Integral' spin button controls the damping effect on PV by
setting the value of INT_001 in the Cascade DataHub.\n\n   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

\n                     Monitor\n
\n   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.\n\n   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

\n                     Monitor\n
\n   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.\n\n   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

\n                     Monitor\n
\n   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.\n\n   The Automatic
mode button is set to OFF, since automatic mode is not necessary here.

#END
#3.11 Out-of-control radio button

\n                     Monitor\n
\n   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.\n\n   The Automatic mode button is set to OFF, since automatic
mode is not necessary here.

#END
#4 DataHub Viewer

\n             DataHub Viewer\n\n   The
DataHub Viewer is a Cogent utility (xdhview in GTK, phdhview in
Photon) that gives you a window into the Cascade DataHub.\n\n   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.\n\n   From the DataHub Viewer you can select any point and
manually change its attributes.

#END
#5 Log

\n                      Log\n
\n   Log is a Gamma program (log.g) that demonstrates the Cascade
TextLogger.\n\n 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. \n\n In Linux, Log uses
gnuplot to read the Cascade TextLogger files and generate plots of the
data.

#END
#5.1 Any radio button

\n                      Log\n
\n   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.\n\n Only the new values are
written.  Points whose values haven't changed are marked with an
asterisk (*).\n\n This is the default setting.

#END
#5.2 Fill radio button

\n                      Log\n
\n   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.\n\n   Values for all the other
points are filled in, even if they haven't changed.

#END
#5.3 All radio button

\n                      Log\n
\n   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.\n\n   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

\n                      Log\n
\n   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.\n\n   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

\n                      Log\n
\n   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.\n\n   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

\n                      Log\n
\n   The 'Log to' button starts the Cascade TextLogger, using the
configuration file tl.cfg, and according to the 'Collect' and 'Log to'
options.\n\n   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

\n                      Log\n
\n   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

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

#END
#5.9 Plot Recent button

\n                      Log\n
\n   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.\n\n   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

\n                      Log\n
\n   The 'All' plot button calls gnuplot to create a continuously updated plot
of the output.dat file.\n\n   NOTE: Because the data for this plot is
ever-increasing, gnuplot will use progressively more system resources
to construct a plot.\n\n   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:
\n------------Collect------------
\nAny: logs any new data.
\nFill: logs any new data, filling in existing data.
\nAll: logs data only when all values have changed.
\n
\nInsert Text: Adds a line of text to the log.
\n(note: the '#' is a comment character for gnuplot.)
\n
\nSend Cmd: Sends a command to the Cascade TextLogger.

#END
#6 History

\n                      History\n
\n   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

\n                      History\n
\n   The 'Record Values' button enables the Cascade Historian to start
recording data for MV and PV for the number of seconds indicated.
\n\n   The data for both of these points will be collected as long
as the PID Emulator is running.

#END
#6.3 Update Display

\n                      History\n
\n   The 'Update display' button sends a query to the Cascade Historian
based on the current Interpolator options.\n\n   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.
\n\n   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

\n                      History\n
\n   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

\n                      History\n
\n   The 'Periodic' interpolator option plots the Y history (either MV
or PV) versus time.  \n\n   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

\n                      History\n
\n   The 'Relative' interpolator option plots the Y history (either MV
or PV) versus the X history (also either MV or PV).  \n\n   This
interpolator inserts an extra value into the Y history for each value
in the X history.

#END
#6.34 FixedRelative

\n                      History\n
\n   The 'FixedRelative' interpolator option plots the Y history (either
MV or PV) versus the X history (also either MV or PV).
\n\n   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

\n                      History\n
\n   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

\n                      History\n
\n   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

\n                      History\n

\n   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

\n                      History\n
\n   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

\n                      History\n
\n   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

\n                      History\n
\n   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.\n\n   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

\n                      History\n
\n   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

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

#END
#6.52 Deadband on, prior off

\n                      History\n

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

#END
#6.53 Deadband on, prior on

\n                      History\n
\n   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

\n                      History\n
\n   The Deadband Types window lets you set the type of deadband on data
collected for MV or PV, to filter out redundant data.\n\n   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

\n                      History\n
\n   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

\n                      History\n
\n   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

Copyright 1995-2002 by Cogent Real-Time Systems, Inc.