SimpleAverage.g

SimpleAverage.g — computes average point values over a period of time.

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.

/* 
 * Compute simple averages for points over a selected time period.
 * Write the average to a new data point continuously or 
 * periodically as the input changes, resetting the average at 
 * the end of the period.
 */

require ("Application");
require ("ModelSupport");

class SimpleAverage Application
{
    // One of "day", "hour", "minute", "10sec"
    period = "10sec";
	
    // A pattern containing %s where the point name is inserted to 
    // create the average point name
    outputPattern = "%sAvg";
	
    // Select running average (constant updating) or write at the 
    // end of period.  Use t for running average, or nil for update 
    // at the end of the period.
    isRunningAverage = t;
	
    // Do not edit this
    accumulators = new Dictionary();
    model = new ModelEmitter();
}

/*
 * This is the start-up method.  Add code here to monitor other data 
 * points by calling .monitor for each point, or by iterating through 
 * all points to monitor those that you want.
 */
method SimpleAverage.constructor ()
{
    .monitor("DataPid:PID1.Mv");

    // After setting up the monitored points, emit the model to place 
    // the points into the point heirarchy, then start the timer to 
    // reset the average periodically.
    .model.Emit();
    .startResetTimer();
}

/* -------------- Implementation starts here ----------------- */

class Accumulator
{
    point;
    sum = 0;
    count = 0;
}

method Accumulator.getAverage()
{
    .count > 0 ? .sum / .count : 0;
}

method Accumulator.reset()
{
    .sum = .count = 0;
}

method SimpleAverage.update (pointSym, value)
{
    local accumulator = .accumulators[pointSym];
    if (!accumulator)
    {
        accumulator = new Accumulator();
        accumulator.point = pointSym;
        .accumulators[pointSym] = accumulator;
    }
    accumulator.count++;
    accumulator.sum += number(value);
	
    if (.isRunningAverage)
        .writeAverage(accumulator);
}

method SimpleAverage.writeAverage(accumulator)
{
    local avgName = format(.outputPattern, string(accumulator.point));
    local value = accumulator.getAverage();
    //princ (avgName, " = ", value, "\n");
    datahub_write(avgName, value, t);
}

method SimpleAverage.monitor(pointName)
{
    local sym = symbol(pointName);
    local current;
    .OnChange(sym, `(@self).update(this, value));
    if (!undefined_p(current = eval(sym)))
        .update(sym, current);
		
    local avgName = format(.outputPattern, pointName);
    .model.MapPoint(avgName, ".", "R8", "r");
}

method SimpleAverage.reset()
{
    //princ ("Reset\n");
    with accumulator in .accumulators.values do
    {
        if (!.isRunningAverage)
            .writeAverage(accumulator);
        accumulator.reset();
    }
}

method SimpleAverage.startResetTimer()
{
    if (.period == "10sec")
    {
        .TimerAt(nil, nil, nil, nil, nil, list(0, 10, 20, 30, 40, 50), 
                 `(@self).reset());
    }
    else if (.period == "minute")
    {
        .TimerAt(nil, nil, nil, nil, nil, 0, `(@self).reset());
    }
    else if (.period == "hour")
    {
        .TimerAt(nil, nil, nil, nil, 0, 0, `(@self).reset());
    }
    else if (.period == "day")
    {
        .TimerAt(nil, nil, nil, 0, 0, 0, `(@self).reset());
    }
    else
    {
        princ ("No period set - will average over all time\n");
    }
}

/* Start the program by instantiating the class. */
ApplicationSingleton (SimpleAverage);