FixQuality.g

FixQuality.g — changes point quality for OPC clients that treat bad quality as a disconnection.

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 application monitors a set of points in the "input domain"
   and copies them to the "output domain".  If the quality of the
   input point is not GOOD, then the script modifies the point value
   to -1 and the quality to GOOD.  This is to handle an OPC client
   that treats bad quality as a disconnection.
 * 
 * To configure this application, modify the class variables:
 *    domain_in = the name of the input domain
 *    domain_out = the name of the output domain
 *    value_if_bad = the value to substitute on the point if the
 *                   quality is bad. If this is nil, then do no
 *                   value substitution.
 */
require ("Application");

class FixQuality Application
{
    domain_in = "test";
    domain_out = "test2";
    value_if_bad = -1;
}

/* Monitor a point.  This includes creating the point if it does
   not exist, and then creating the output domain's mirror of the
   point.  This function also sets up an event handler to map any
   future changes of the point into the output domain. */
method FixQuality.Monitor (ptname)
{
    local		outname, ptsym;
	
    outname = string(.domain_out, ":", ptname);
    ptname = string(.domain_in, ":", ptname);
    .OnChange(symbol(ptname),
	      `(@self).BridgeQuality(#@ptname, #@outname));
    datahub_command(format("(create %s 1)", stringc(ptname)), 1);
    ptsym = symbol(ptname);
    if (!undefined_p(eval(ptsym)))
        .BridgeQuality(ptname, outname);
}

/* This is the function that does the work of mapping from the
   input domain to the output domain. */
method FixQuality.BridgeQuality(ptname, outname)
{
    local		info = PointMetadata(symbol(ptname));
    local		value = info.value;
    if (info.quality != OPC_QUALITY_GOOD && .value_if_bad)
        value = .value_if_bad;
    datahub_write(outname, value, 1,
		  OPC_QUALITY_GOOD, info.timestamp);
}

method FixQuality.MonitorDomain(domain)
{
    local		points = datahub_points(domain, nil);
    with point in points do
    {
        .Monitor(point.name);
    }
}

/* This is the mainline of the program.  You can either call
   .Monitor("pointname") for each point, or you can call
   .MonitorDomain(.domain_in) to monitor all existing points in
   the input domain.  If you choose to monitor the whole domain,
   you must re-run this application whenever new points are added
   to the domain. */
method FixQuality.constructor ()
{
    .Monitor("point001");
    .Monitor("point002");
    .MonitorDomain(.domain_in);
}

/* Any code to be run when the program gets shut down. */
method FixQuality.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 (FixQuality);