AutoCalculation.g — automatically calculates formulas based on data points.
Please refer to Section 3.1, “How to Run a Script” for more information on using scripts. |
/* * Automatically calculate formulas based on data points. Create data points where * necessary to store the results back to the DataHub's data set. * * To use: * - create a file, like c:/tmp/calculations.txt * - in the file, create any number of calculations of the form * $default:test = $DataPid:PID1.Mv * 10; * $default:test2 = $DataPid:PID1.Mv / 10; * - change the fileName member in the AutoCalculation class below to refer to your file * - run the script * * Any symbol in the calculation of the form $domain:name is assumed to be a DataHub point, * and will be created if necessary. The point on the left hand side of the equal sign will * be automatically updated whenever any point on the right hand side of the equal sign * changes. * * You can include complex Gamma expressions, like: * $default:output = progn { * local a = $DataPid:PID1.Mv; * local b = $DataPid:PID1.Pv; * if (b != 0) * a / b; * else * a; * }; * * You can define functions within this file, though it is better to put functions into a * separate script file: * * function average(a,b) * { * a + b / 2; * } * * $default:output = average($DataPid:PID1.Mv, $DataPid:PID1.Pv); */ require ("Application"); class AutoCalculation Application { fileName = "C:/tmp/calculations.txt"; fp; } class Computation { app; // the Application instance defining this computation output; // a symbol inputs; // a list of symbols code; // the code to execute } method Computation.constructor(app, expression) { .app = app; .code = expression; .output = .findOutput(expression); .inputs = .findInputs(expression); if (.output) { datahub_command(format("(create %s 1)", stringc(.output)), 1); with input in .inputs do { datahub_command(format("(create %s 1)", stringc(input)), 1); .app.OnChange(input, `(@self).compute()); } } .compute(); } method Computation.compute() { try { eval(.code); } catch { princ ("Assignment to ", .output, " failed: ", _last_error_, "\n"); } } method Computation.findOutput (expr) { if (car(expr) == #setq) cadr(expr); else nil; } method Computation.findInputsRecursive (expr) { local inputs, partial; if (list_p(expr)) { with part in expr do { partial = .findInputsRecursive(part); inputs = nappend(inputs, partial); } } else if (symbol_p(expr) && strchr(string(expr), ":") != -1) { inputs = cons(expr, inputs); } inputs; } method Computation.findInputs (expr) { .findInputsRecursive(cddr(expr)); } method AutoCalculation.readFile() { if ((.fp = open(.fileName, "r", t)) != nil) { //create some local variables local line; //loop until we have read the entire file. while((line = read(.fp)) != _eof_) { local comp = new Computation(self, line); } //once we have read the entire file we need to close it. close(.fp); } else { princ ("AutoCalculation: Could not open file: ", .fileName, ": ", strerror(errno()), "\n"); } } /* Write the 'main line' of the program here. */ method AutoCalculation.constructor () { .readFile(); } /* Any code to be run when the program gets shut down. */ method AutoCalculation.destructor () { } /* Start the program by instantiating the class. */ ApplicationSingleton (AutoCalculation);
Copyright © 1995-2010 by Cogent Real-Time Systems, Inc. All rights reserved.