3.3. Set up Event Handlers

The Gamma application will normally define functions to be called when an event occurs. In ODBC applications, this is most commonly to write live data into the relational database. Another word for an event is a "trigger". It is up to you to decide the best trigger for writing data into the database.

An event handler will look something like this:

.OnChange (#$DataSim:Sine, `(@self).AddRecord (this, value));

This statement says that when the DataHub point DataSim:Sine changes, we want to call our application's AddRecord method with two arguments. The special variables this and value are always defined to be the point name and the point value respectively when running an OnChange handler. We might define our AddRecord method like this:

method MyODBCScript.AddRecord (pointname, newvalue)
{
    local  record = new (tableclass);
    local  timestamp;
	
    timestamp = localtime (PointGetUnixTime(pointname));
    timestamp = format ("%d-%02d-%02d %02d:%02d:%02d",
        timestamp.year + 1900, timestamp.mon + 1,
        timestamp.mday, timestamp.hour, timestamp.min,
        timestamp.sec);
    record.ptname = string (pointname);
    record.ptvalue = number (newvalue);
    record.pttimestamp = timestamp;
    record.ptquality = GetQualityName(PointMetadata(pointname).ptquality);
    .conn.Insert (record);
    record;
}

If you would like to add a record at a specific interval rather than on a value change, you could create a timer:

timerid = every (0.5, `(@self).AddRecord (#$DataSim:Sine, $DataSim:Sine));

This statement will add a new record to the database every ½ second. In this case, we need to specify the name of the point, $DataSim:Sine, as part of the AddRecord call because the special variables this and value are not defined during a timer call. The first reference to $DataSim:Sine is protected from evaluation during the call using the # modifier, so its name is passed to the first argument when the expression is evaluated (when the timer occurs). The second reference is not protected from evaluation, so its value is passed to the second argument.

You need to keep track of outstanding timers so that you can clean them up during the destructor:

method MyODBCScript.destructor ()
{
  cancel (timerid);
}