TagMonitor.g

TagMonitor.g — monitors DataHub points for changes in quality or failure to change value.

Code

[Note]

The code for this and other example scripts can be found in the DataHub distribution archive, typically at this location:

C:\Program Files\Cogent\Cogent DataHub\scripts\

Please refer to Section 3.1, “How to Run a Script” for more information on using scripts.

/*
 * This script monitors tags (or DataHub points) for two conditions:
 *
 * 1) change of quality
 * 2) failure to change within a time period
 *
 * For each of these, the script creates synthetic points
 * (the "target") that hold the result of monitoring the watch points.
 * Email and * database events can then be triggered from the
 * synthetic points.
 *
 * You can modify the constructor function in this script to change
 * the point names, or to add additional watch conditions as needed.
 */

require ("Application");

class TagMonitor Application
{
}

/*
 * Set up a watch tag and a target tag such that the quality of the
 * watch tag is copied into the value of the target tag.
 */
method TagMonitor.copyQuality(poll_seconds, watch, target)
{
    // Ensure that the input and output tags exist.
    datahub_command(format("(create %s 1)", stringc(watch)), 1);
    datahub_command(format("(create %s 1)", stringc(target)), 1);
	
    // Periodically copy the quality of the watch point into
    // the value of the target
    .TimerEvery(poll_seconds,
		`set(#@target, PointMetadata(#@watch).quality));
}

/*
 * Set up a watch tag, a target tag and a time such that the target
 * tag will be set to 1 if the watch tag has changed within the timer
 * period, or zero if the watch tag has not changed within the time
 * period.  The time period is specified by dead_seconds, which may
 * be fractional.
 */
method TagMonitor.copyChangeStatus(dead_seconds, watch, target)
{
    // Ensure that the input and output tags exist.
    datahub_command(format("(create %s 1)", stringc(watch)), 1);
    datahub_command(format("(create %s 1)", stringc(target)), 1);
	
    // Start the watch point off as having changed
    setprop(watch, #has_changed, t);
	
    // Whenever the watch point changes, set its property
    // "has_changed" to t.
    .OnChange(watch, `(@self).watchHasChanged(#@watch, #@target));
    .TimerEvery(dead_seconds,
		`(@self).checkChange(#@watch, #@target));
}

/*
 * A callback function that checks for a change in a point and puts
 * a 1 or 0 into the target.  Reset the changed flag to zero.
 */
method TagMonitor.checkChange(watch, target)
{
    set(target, getprop(watch, #has_changed) ? 1 : 0);
    setprop(watch, #has_changed, nil);
}

/*
 * A callback whenever a change watch point changes.  We use this to
 * change from 0 to 1 as soon as we see a change in a watch point
 * instead of waiting for the poll delay.
 */
method TagMonitor.watchHasChanged(watch, target)
{
    setprop(watch, #has_changed, t);
    set(target, 1);
}

/* Write the 'main line' of the program here.
 *
 * As written, the points to watch for quality and change, as well as
 * the target points to modify, are all in the "default" domain,
 * as follows:
 *
 * Point to watch for quality:  default:quality_watch
 * Point to watch for change:   default:change_watch
 * Target point for quality:    default:quality_target
 * Target point for change:     default:change_target
 *
 * You can change these to different domain and point names.  Also,
 * you can add any number of other points to monitor quality and
 * change, following the same syntax.
 *
 * The first argument of .copyQuality is the poll rate in seconds on
 * the quality of the point.  The first argument of .copyChangeStatus
 * is the number of "dead" seconds to wait for a change, before
 * notifiying of a failure.  
 */
method TagMonitor.constructor ()
{
    .copyQuality(1, #$default:quality_watch,
                 #$default:quality_target);
    .copyChangeStatus(5, #$default:change_watch,
                      #$default:change_target);
}

/* Any code to be run when the program gets shut down. */
method TagMonitor.destructor ()
{
}

/* Start the program by instantiating the class.  If your
 * constructor code does not create a persistent reference to
 * the instance (self), then it will be destroyed by the
 * garbage collector soon after creation.  If you do not want
 * this to happen, assign the instance to a global variable, or
 * create a static data member in your class to which you assign
 * 'self' during the construction process.  ApplicationSingleton()
 * does this for you automatically. */
ApplicationSingleton (TagMonitor);