/*--------------------------------------------------------------------
* File: phhistory.g
*
* Description: Demonstrates the Cascade Historian
*
* Classes: HistoryWindow
* DeadbandType
*
* Functions and methods by category:
*
* Int & Query: InterpolatorSettings.assign_values
* InterpolatorSettings.get_data
* send_query
* countdown
* record_data
* show_data
* query_refresh
* Deadbanding: reset_deadbands
* db_prep_query
* DeadbandType.constructor
* db_options
* create_dbtype_win
* Plotting: make_CwGraph_points
* make_graph
* Window: HistoryWindow.constructor
* PtText.set_sensitive
* PtComboBox.set_sensitive
* HistoryWindow.allow_entry_values
* HistoryWindow.change_int
* create_history
* Main main
*------------------------------------------------------------------*/
/* Get access to the library of common functions. */
require("lib/common.g");
require_lisp("Profile");
anyver_loadlibs();
/* Keep track of all child processes that this process has started.*/
Children := nil;
/********************************************************
* INTERPOLATOR and QUERY Code *
********************************************************/
/*--------------------------------------------------------------------
* Method: InterpolatorSettings.assign_values
* Returns: t or nil
* Description: Assigns the values from the interpolator entry widgets
* to the appropriate instance variables of the class.
*------------------------------------------------------------------*/
method InterpolatorSettings.assign_values(e1, e2, e3, e4, e5, e6)
{
.y_history = assign_history(.dbflag, .y_history, e1.text_string);
.start = number(e2.text_string);
.duration = number(e3.text_string);
.x_history = assign_history(.dbflag, .x_history, e4.text_string);
.interval = number(e5.text_string);
.max_gap = number(e6.text_string);
}
/*--------------------------------------------------------------------
* Method: InterpolatorSettings.get_data
* Returns: a list of x-data and y-data, as strings
* Description: Sends a query to the Historian and receives the data.
* Activated by the send_query function.
*------------------------------------------------------------------*/
method InterpolatorSettings.get_data()
{
local tsk, intpl, buf_length, alldata, count, dur, data, outfile;
local xdata = list();
local ydata = list();
local midnite = find_midnite();
/* Make sure there are valid values in the entry widgets.*/
if (undefined_p(.start) || (!number_p(.start)))
{
.start = 0;
hw.StartEnt.text_string = "0";
}
if (undefined_p(.duration) || (!number_p(.duration))
|| (.duration <= 0))
{
.duration = 10;
hw.DurEnt.text_string = "10";
}
if (undefined_p(.interval) || (!number_p(.interval))
|| (.interval < .01))
{
.interval = .01;
hw.IntEnt.text_string = "0.01";
}
if ((tsk = locate_task("demohistdb", nil)) != nil)
{
intpl = self.set_interpolator(tsk);
buf_length = caddr(send(tsk, `bufferIdLength(intpl)));
if(!((.fn == "TimeSetup") || (.fn == "RelSetup")))
hw.NumPts.text_string = string(buf_length);
alldata = list();
count = 0;
while (count < buf_length)
{
if((buf_length - count) > 100)
dur = 100;
else
dur = buf_length - count;
data = send(tsk, `bufferIdDataAscii(intpl, @count, @dur));
data = cddr(cdr(data));
alldata = append(alldata, data);
count = count + 100;
}
if (outfile = open("/tmp/cogentdemo/hsoutput.dat", "w"))
if (buf_length == 0)
{
writec(outfile, "# Sorry, no data matched your query.");
writec(outfile, string("\n", midnite, " 0",
"\n", (midnite + 1), " 0"));
close(outfile);
}
else
{
with d in alldata do
writec(outfile, string(car(d), " ", cadr(d), "\n"));
close(outfile);
}
while (alldata != nil)
{
if(.fn == "TimeSetup" ||
.fn == "NoInterpolator" || .fn == "Periodic")
xdata = cons(caar(alldata) - midnite, xdata);
else
xdata = cons(caar(alldata), xdata);
ydata = cons(cadar(alldata), ydata);
alldata = cdr(alldata);
}
xdata = reverse(xdata);
ydata = reverse(ydata);
send(tsk, #bufferIdDestroy(intpl));
}
list(xdata, ydata);
}
/*--------------------------------------------------------------------
* Function: send_query
* Returns: t or nil
* Description: Calls the necessary functions to send a query to the
* Historian, and handles the data returned. It is activated
* by the "Record" button popping out, or any radio button.
*------------------------------------------------------------------*/
function send_query(iset, text, parent, ent1, ent2,
ent3, ent4, ent5, ent6, button)
{
local fnholder, datalist, minmaxlist;
if ((button == hw.NoIntBut || button == hw.PeriodBut ||
button == hw.RelBut || button == hw.FixRelBut ||
button == hw.DisplayBut || button == hw.RecBut))
iset.dbflag = "NONE";
iset.assign_values(ent1, ent2, ent3, ent4, ent5, ent6);
datalist = list();
fnholder = iset.fn;
/* Assign a name for the setup query. */
if ((iset.fn == "NoInterpolator") || (iset.fn == "Periodic"))
iset.fn = "TimeSetup";
else
iset.fn = "RelSetup";
/* Make the setup query and assign minimum and maximum values. */
datalist = iset.get_data();
if (car(datalist) && cadr(datalist))
minmaxlist = list(min_max(car(datalist)), min_max(cadr(datalist)));
else
minmaxlist = nil;
/* Make the actual query. */
iset.fn = fnholder;
datalist = iset.get_data();
show_data(text, iset, parent, button, datalist, minmaxlist);
}
/*--------------------------------------------------------------------
* Function: countdown
* Returns: an integer
* Description: Called by record_data to facilitate the time count-down.
* This functionality had to be separated out from the callback.
*------------------------------------------------------------------*/
function countdown(starttime)
{
starttime - clock();
}
RECORD_TIME = 5;
/*--------------------------------------------------------------------
* Function: record_data
* Returns: an integer (timer number), or nil
* Description: Records data for the specified time, then sends a query.
*------------------------------------------------------------------*/
function record_data(but1, but2, iset, text, window, e1, e2, e3, e4, e5, e6)
{
if (but1.switched_on())
{
local time = clock() + RECORD_TIME;
text.text_string = string("Recording,please wait.\nSeconds remaining: ",
RECORD_TIME);
numtimer = every (1, `((@text).text_string = string(substr((@text).text_string, 0, 42),
string((countdown(@time))))));
e3.text_string = string(RECORD_TIME + 1);
iset.set_defaults(but1, e2);
send_hs_command(but1, "enable", e1.text_string, nil);
after(RECORD_TIME, `((@but1).flags = cons(Pt_SET, nil)));
after((RECORD_TIME + .1), `(send_hs_command(@but1, "enable", (@e1).text_string, nil)));
after((RECORD_TIME + .1), `(cancel(numtimer)));
after((RECORD_TIME + .15), `(query_refresh(nil, nil)));
after((RECORD_TIME + .25), `PtFlush());
}
}
/*--------------------------------------------------------------------
* Function: show_data
* Returns: t or nil
* Description: Shows interpolated query results from the Cascade Historian
* in the text widget and plots the results in the CwGraph widget.
*------------------------------------------------------------------*/
function show_data(txt_wgt, int_set, parent, button, datalist, minmaxlist)
{
local start_time, infile, line, string_list, line_ret;
local x_is_time, x_min, x_max, y_min, y_max, x_list, y_list;
local outstring = open_string ("");
x_list = car(datalist);
y_list = cadr(datalist);
txt_wgt.text_string = "";
start_time = find_midnite();
if (int_set.fn == "NoInterpolator" || int_set.fn == "Periodic")
{
x_is_time = t;
txt_wgt.text_string = "Query results: \n Time Y History\n";
}
else
{
x_is_time = nil;
txt_wgt.text_string = "Query results: \nX-hist / Y-hist\n";
}
infile = open("/tmp/cogentdemo/hsoutput.dat", "r");
if (infile)
{
line = nil;
while(line != _eof_)
{
line = read_line(infile);
line_ret = "";
if (line != "Unexpected end of file")
{
if ((strstr(line,"#") != -1))
{
writec (outstring, line);
read_line(infile);
read_line(infile);
}
else
{
string_list = string_split(line, " ", 2);
if (x_is_time)
{
line_ret = string(number(car(string_list)) - start_time,
" ", cadr(string_list),"\n");
}
else
{
line_ret = string(number(car(string_list)),
" ", cadr(string_list),"\n");
}
writec (outstring, line_ret);
}
}
}
txt_wgt.text_string = string(txt_wgt.text_string, string_file_buffer(outstring));
if(x_list && y_list && minmaxlist != nil)
{
if (x_is_time)
{
x_min = caar(minmaxlist);
x_max = cadar(minmaxlist);
}
else
{
x_min = floor(caar(minmaxlist));
x_max = ceil(cadar(minmaxlist));
}
y_min = floor(caadr(minmaxlist));
y_max = ceil(car(cdadr(minmaxlist))) + 1;
PtSetParentWidget(parent);
make_graph(x_min, x_max, y_min, y_max,
x_list, y_list, int_set.dbflag);
}
close(infile);
}
}
/*--------------------------------------------------------------------
* Function: query_refresh
* Returns: t or nil
* Description: Sets the interpolator, resets the deadband, and sends a
* query. Used by callbacks on the four interpolator buttons,
* the Update display button, and a timer on the Record button.
*------------------------------------------------------------------*/
function query_refresh(button, title_string)
{
if (title_string)
hw.change_int(button, title_string);
reset_deadbands();
send_query(hw.int_set, hw.Text, hw.PtHist, hw.YHistEnt,
hw.StartEnt, hw.DurEnt, hw.XHistEnt, hw.IntEnt,
hw.GapEnt, button);
}
/********************************************************
* DEADBANDING Code *
********************************************************/
/*--------------------------------------------------------------------
* Function: reset_deadbands
* Returns: an integer
* Description: Clears all traces and sets the Full data set (no deadband)
* option. Called when non-deadband buttons are activated.
*------------------------------------------------------------------*/
function reset_deadbands()
{
hw.DBBut.flags = cons(Pt_SET, nil);
hw.DBPBut.flags = cons(Pt_SET, nil);
if(!undefined_p(GraphWidget))
{
CwGraphClearTrace (GraphWidget, 0);
CwGraphClearTrace (GraphWidget, 1);
CwGraphClearTrace (GraphWidget, 2);
}
hw.DBNoneBut.flags = Pt_SET;
}
/*--------------------------------------------------------------------
* Function: db_prep_query
* Returns: t or nil
* Description: Sends a query when a Deadband button is toggled on, and
* erases the corresponding graph trace when a Deadband button
* is untoggled.
*------------------------------------------------------------------*/
function db_prep_query(button)
{
if ((button.flags & Pt_SET) != 0)
send_query(hw.int_set, hw.Text, hw.PtHist, hw.YHistEnt,
hw.StartEnt, hw.DurEnt, hw.XHistEnt, hw.IntEnt,
hw.GapEnt, button);
else
{
if(!undefined_p(GraphWidget))
{
if(button == hw.DBNoneBut)
CwGraphClearTrace (GraphWidget, 0);
else if(button == hw.DBBut)
CwGraphClearTrace (GraphWidget, 1);
else if(button == hw.DBPBut)
CwGraphClearTrace (GraphWidget, 2);
}
}
}
/********************************************************
* DEADBAND TYPE WINDOW Code *
********************************************************/
/*--------------------------------------------------------------------
* Class: DeadbandType
* Description: Creates the Deadband Type window using PhabAttachWidgets.
*------------------------------------------------------------------*/
class DeadbandType
{
window;
}
PhabAttachWidgets (DeadbandType, anyos_assign("deadband_widgetfile"));
/*--------------------------------------------------------------------
* Method: DeadbandType.constructor
* Returns: the root widget of a widget hierarchy
* Description: Instantiates a DeadbandType window.
*------------------------------------------------------------------*/
method DeadbandType.constructor ()
{
.window = PhabRoot(.PhabInstantiate (t));
}
/*--------------------------------------------------------------------
* Function: db_options
* Returns: a PtText widget
* Description: Creates a PtText widget, gives it a position, and gives
* it a callback to update the corresponding value in the
* parameter array.
*------------------------------------------------------------------*/
function db_options (p_array, index, col, row)
{
local option;
local cols = [86, 148];
local rows = [55, 86, 127, 157];
option = new(PtText);
option.SetDim(40, 20);
option.fill_color = 0xffffee;
option.border_width = 1;
option.text_string = (string(p_array[index]));
option.SetPos(cols[col], rows[row]);
PtAttachCallback(option, Pt_CB_TEXT_CHANGED,
`((@p_array)[@index] = number((@option).text_string)));
option;
}
/*--------------------------------------------------------------------
* Function: create_dbtype_win
* Returns: a Deadband Type window, or a destroyed instance
* Description: Creates the Deadband Type window.
*------------------------------------------------------------------*/
function create_dbtype_win (!point_list, button)
{
local db1, db2, pa1, pa2;
if ((button.flags & Pt_SET) != 0)
{
if (undefined_p(db) || db.window == nil)
{
db = new (DeadbandType);
db.DeadBandWindow.SetPos(150, 300);
attach_msg(db.DeadBandWindow, "6.54", "6");
db1 = car(point_list);
db2 = cadr(point_list);
pa1 = array(db1.absolute, db1.percent, db1.timelimit, db1.countlimit);
pa2 = array(db2.absolute, db2.percent, db2.timelimit, db2.countlimit);
db_options(pa1, 0, 0, 0);
db_options(pa1, 1, 0, 1);
db_options(pa1, 2, 0, 2);
db_options(pa1, 3, 0, 3);
db_options(pa2, 0, 1, 0);
db_options(pa2, 1, 1, 1);
db_options(pa2, 2, 1, 2);
db_options(pa2, 3, 1, 3);
attach_msg(db.CancelBut, "6.55", "6.5");
attach_msg(db.OKBut, "6.56", "6.5");
PtAttachCallback(db.CancelBut, Pt_CB_ACTIVATE,
`((@button).flags = cons(Pt_SET, nil)));
PtAttachCallback(db.CancelBut, Pt_CB_ACTIVATE,
`PtDestroyWidget((@db).window));
PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
`(@db1).set_parms((@db).OKBut, @pa1));
PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
`(@db2).set_parms((@db).OKBut, @pa2));
PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
`((@button).flags = cons(Pt_SET, nil)));
PtAttachCallback(db.OKBut, Pt_CB_ACTIVATE,
`PtDestroyWidget((@db).window));
PtAttachCallback(db.window, Pt_CB_DESTROYED,
`((@button).flags = cons(Pt_SET, nil)));
PtAttachCallback(db.window, Pt_CB_DESTROYED,
`((@db).window = nil));
}
if(db)
PtRealizeWidget (db.window);
db;
}
else
PtDestroyWidget (db.window);
}
/********************************************************
* PLOTTING *
********************************************************/
/*--------------------------------------------------------------------
* Function: make_CwGraph_points
* Returns: a list
* Description: Applied to the x and y arguments of the CwGraphAddXYPoints()
* function, which are lists. This function destructively
* modifies those lists, adding extra values that, when plotted
* by CwGraph, render as small, diamond-shaped points. The xval
* parameter must be set to t for the x-coordinate, and to nil
* for the y coordinate.
*------------------------------------------------------------------*/
function make_CwGraph_points (ptlist, ptsize, xval)
{
parray = list_to_array(ptlist);
i = 0;
if(xval)
{
/* Add x-values to the trace. */
while (i < length(parray))
{
insert(parray, i+1, parray[i] + (ptsize));
insert(parray, i+2, parray[i]);
insert(parray, i+3, parray[i] - (ptsize));
insert(parray, i+4, parray[i]);
insert(parray, i+5, parray[i] + (ptsize));
insert(parray, i+6, parray[i]);
i = i + 7;
}
}
else
{
/* Add y-values to the trace. */
while (i < length(parray))
{
insert(parray, i+1, parray[i]);
insert(parray, i+2, parray[i] - (ptsize));
insert(parray, i+3, parray[i]);
insert(parray, i+4, parray[i] + (ptsize));
insert(parray, i+5, parray[i]);
insert(parray, i+6, parray[i]);
i = i + 7;
}
}
ret = array_to_list(parray);
}
/*--------------------------------------------------------------------
* Function: make_graph
* Returns: a CwGraph widget
* Description: Sets up a CwGraph widget to plot the query results.
*------------------------------------------------------------------*/
function make_graph (xmin, xmax, ymin, ymax, xlist, ylist, dband)
{
local grf;
/* Set a size for the points created by make_CwGraph_points. */
local xdist = (xmax - xmin) * .007;
local ydist = (ymax - ymin) * .007;
if (undefined_p(GraphWidget) || !GraphWidget)
{
/* Make a new graph, if one doesn't already exist. */
PtSetParentWidget (hw.GraphPane);
GraphWidget = new(CwGraph);
GraphWidget.SetArea(0, 0, hw.GraphPane.dim.w, hw.GraphPane.dim.h);
GraphWidget.fill_color = 0xffffe5;
GraphWidget.bot_border_color = 0x000000;
GraphWidget.graph_y_label_left = "Y history";
GraphWidget.graph_x_font = anyos_assign("graph_font");
GraphWidget.graph_y_font_left = anyos_assign("graph_font");
GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_RIGHT);
GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_LABEL_RIGHT);
GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_AXIS_TITLE_RIGHT);
GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_MAJOR_TICK_RIGHT);
GraphWidget.ClearBit(#graph_flags, Cw_GRAPH_Y_MINOR_TICK_RIGHT);
PtAttachCallback (hw.GraphPane, Pt_CB_RESIZE,
`GraphWidget.SetArea(0, 0, hw.GraphPane.dim.w,
hw.GraphPane.dim.h));
}
/* Change the tick size and scale of the existing graph for a new data plot. */
grf = GraphWidget;
grf.graph_x_major_tick = (xmax - xmin) / 5;
grf.graph_x_minor_tick = (xmax - xmin) / 25;
grf.graph_y_major_tick_left = (ymax - ymin) / 5;
grf.graph_y_minor_tick_left = (ymax - ymin) / 25;
grf.graph_xmin = xmin;
grf.graph_xmax = xmax;
grf.graph_ymin_left = ymin;
grf.graph_ymax_left = ymax;
grf.graph_traces = 3;
if (xmax > 1000)
grf.graph_x_label = "Time (number of seconds after midnight)";
else
grf.graph_x_label = "X history";
/* Assign trace limits and colors for the new data plot. */
CwGraphSetYLimits(grf, 0, ymin, ymax);
CwGraphSetYLimits(grf, 1, ymin, ymax);
CwGraphSetYLimits(grf, 2, ymin, ymax);
CwGraphSetTraceColor(grf, 0, 0xdd00aa);
CwGraphSetTraceColor(grf, 1, 0x0000aa);
CwGraphSetTraceColor(grf, 2, 0x00aa00);
/* Create the traces for the new data plot. */
if(dband == "NONE")
CwGraphAddXYPoints(grf, 0, make_CwGraph_points(xlist, xdist, t),
make_CwGraph_points(ylist, ydist, nil));
else if(dband == "DB")
CwGraphAddXYPoints(grf, 1, make_CwGraph_points(xlist, xdist, t),
make_CwGraph_points(ylist, ydist, nil));
else if(dband == "DBP")
CwGraphAddXYPoints(grf, 2, make_CwGraph_points(xlist, xdist, t),
make_CwGraph_points(ylist, ydist, nil));
PtRealizeWidget(grf);
}
/********************************************************
* HISTORY WINDOW Code *
********************************************************/
/*--------------------------------------------------------------------
* Class: HistoryWindow
* Description: Creates the History window using PhabAttachWidgets.
*------------------------------------------------------------------*/
class HistoryWindow
{
window;
int_set;
}
PhabAttachWidgets (HistoryWindow, anyos_assign("history_widgetfile"));
/*--------------------------------------------------------------------
* Method: HistoryWindow.constructor
* Returns: the root widget of a widget hierarchy
* Description: Instantiates a HistoryWindow.
*------------------------------------------------------------------*/
method HistoryWindow.constructor ()
{
.window = PhabRoot(.PhabInstantiate (t));
}
/*--------------------------------------------------------------------
* Method: PtText.set_sensitive
* Returns: an integer
* Description: Changes the sensitivity of a PtText widget. Called by
* HistoryWindow.allow_entry_values.
*------------------------------------------------------------------*/
method PtText.set_sensitive (val)
{
if (val != 0)
{
self.text_flags = Pt_EDITABLE;
self.fill_color = 0xffffe5;
}
else
{
self.text_flags = cons(Pt_EDITABLE, nil);
self.fill_color = 0xd0d0d0;
}
}
/*--------------------------------------------------------------------
* Method: PtComboBox.set_sensitive
* Returns: an integer
* Description: Changes the fill color of a PtComboBox widget. Called
* by HistoryWindow.allow_entry_values.
*------------------------------------------------------------------*/
method PtComboBox.set_sensitive (val)
{
if (val != 0)
{
self.list_flags = cons (Pt_LIST_INACTIVE, nil);
self.fill_color = 0xffffe5;
}
else
{
self.list_flags = Pt_LIST_INACTIVE;
self.fill_color = 0xd0d0d0;
}
}
/*--------------------------------------------------------------------
* Method: HistoryWindow.allow_entry_values
* Returns: t or nil
* Description: Sets the three specialized parameter entry widgets sensitive
* or non-sensitive. Called by HistoryWindow.change_int().
*------------------------------------------------------------------*/
method HistoryWindow.allow_entry_values(e1, e2, e3)
{
.XHistEnt.set_sensitive(e1);
.IntEnt.set_sensitive(e2);
.GapEnt.set_sensitive(e3);
}
/*--------------------------------------------------------------------
* Method: HistoryWindow.change_int
* Returns: t
* Description: Responding to a click on a "Choose an Interpolator" radio
* button, this method calls the allow_entry_values() function
* on the active button.
*------------------------------------------------------------------*/
method HistoryWindow.change_int(button, str)
{
if (button.switched_on())
{
.int_set.fn = str;
switch (str)
{
case "NoInterpolator":
.allow_entry_values(0, 0, 0);
case "Periodic":
.allow_entry_values(0, 1, 1);
case "Relative":
.allow_entry_values(1, 0, 0);
case "FixedRelative":
.allow_entry_values(1, 1, 0);
}
}
/* To allow for a slow processor */
usleep(10000);
}
/*--------------------------------------------------------------------
* Function: create_history
* Returns: doesn't return
* Description: Creates the History window.
*------------------------------------------------------------------*/
function create_history ()
{
local buttons, version_string;
local hw = new (HistoryWindow);
hw.GraphPane.anchor_flags = Pt_LEFT_ANCHORED_LEFT |
Pt_RIGHT_ANCHORED_RIGHT | Pt_BOTTOM_ANCHORED_BOTTOM |
Pt_TOP_ANCHORED_TOP;
hw.int_set = new(InterpolatorSettings);
hw.change_int(hw.NoIntBut, "NoInterpolator");
hw.SecsEnt.numeric_value = RECORD_TIME;
hw.YHistEnt.text_string = hw.int_set.y_history;
hw.StartEnt.text_string = hw.int_set.start;
hw.DurEnt.text_string = hw.int_set.duration;
hw.XHistEnt.text_string = hw.int_set.x_history;
hw.IntEnt.text_string = hw.int_set.interval;
hw.GapEnt.text_string = hw.int_set.max_gap;
hw.YHistEnt.items = array ("MV_001", "PV_001");
hw.XHistEnt.items = array ("PV_001", "MV_001");
/*Attach message callbacks to buttons and entry widgets.*/
attach_msg(hw.PtHist, "6", "1");
attach_msg(hw.RecBut, "6.2", "6");
attach_msg(hw.DisplayBut, "6.3", "6");
attach_msg(hw.NoIntBut, "6.31", "6");
attach_msg(hw.PeriodBut, "6.32", "6");
attach_msg(hw.RelBut, "6.33", "6");
attach_msg(hw.FixRelBut, "6.34", "6");
attach_msg(hw.YHistEnt, "6.35", "6");
attach_msg(hw.StartEnt, "6.36", "6");
attach_msg(hw.DurEnt, "6.37", "6");
attach_msg(hw.XHistEnt, "6.35", "6");
attach_msg(hw.IntEnt, "6.38", "6");
attach_msg(hw.GapEnt, "6.39", "6");
attach_msg(hw.SetupBut, "6.5", "6");
attach_msg(hw.DBNoneBut, "6.51", "6");
attach_msg(hw.DBBut, "6.52", "6");
attach_msg(hw.DBPBut, "6.53", "6");
/* Display version info and start-up message.*/
display_hs_info(hw.Text);
/* Callback for the PtComboBox entry, number of seconds to record.*/
PtAttachCallback(hw.SecsEnt, Pt_CB_NUMERIC_CHANGED,
`(RECORD_TIME = (@hw).SecsEnt.numeric_value));
/* Callbacks for non-deadband buttons to send a query.*/
PtAttachCallback(hw.NoIntBut, Pt_CB_ACTIVATE,
`query_refresh(@hw.NoIntBut, "NoInterpolator"));
PtAttachCallback(hw.PeriodBut, Pt_CB_ACTIVATE,
`query_refresh(@hw.PeriodBut, "Periodic"));
PtAttachCallback(hw.RelBut, Pt_CB_ACTIVATE,
`query_refresh(@hw.RelBut, "Relative"));
PtAttachCallback(hw.FixRelBut, Pt_CB_ACTIVATE,
`query_refresh(@hw.FixRelBut, "FixedRelative"));
PtAttachCallback(hw.DisplayBut, Pt_CB_ACTIVATE,
`query_refresh(@hw.DisplayBut, nil));
/* A callback to record data, which includes sending a query. */
PtAttachCallback(hw.RecBut, Pt_CB_ACTIVATE,
`(record_data((@hw).RecBut, (@hw).DisplayBut,
(@hw).int_set, (@hw).Text,
(@hw).PtHist, (@hw).YHistEnt,
(@hw).StartEnt, (@hw).DurEnt,
(@hw).XHistEnt, (@hw).IntEnt,
(@hw).GapEnt)));
/* Callbacks to set the deadband flag.*/
PtAttachCallback(hw.DBNoneBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "NONE"));
PtAttachCallback(hw.DBBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "DB"));
PtAttachCallback(hw.DBPBut, Pt_CB_ACTIVATE, `((@hw).int_set.dbflag = "DBP"));
/* A callback for deadband buttons to prepare for and send a query.*/
buttons = list(hw.DBNoneBut, hw.DBBut, hw.DBPBut);
with b in buttons do
{
PtAttachCallback(b, Pt_CB_ACTIVATE, `db_prep_query(@b));
}
/* Deadband setup.*/
dbmv_set = new(DeadbandSettings);
dbmv_set.history = "MV_001";
dbpv_set = new(DeadbandSettings);
dbpv_set.history = "PV_001";
db_list = list(dbmv_set, dbpv_set);
PtAttachCallback(hw.SetupBut, Pt_CB_ACTIVATE,
`create_dbtype_win(@db_list, (@hw).SetupBut));
PtAttachCallback(hw.ExitBut, Pt_CB_ACTIVATE, #exit_program(-1));
hw.PtHist.SetPos(320, 250);
PtRealizeWidget (hw.window);
send_message("nsnames");
hw;
/* Loop forever handling events. */
while(t) next_event();
}
/********************************************************
* MAIN FUNCTION Code *
********************************************************/
/*--------------------------------------------------------------------
* Function: main
* Returns: doesn't return
* Description: Calls the common.g program_startup() function.
*------------------------------------------------------------------*/
function main()
{
program_startup("history", "historyq", #create_history(), "6");
}