4.3. Accessing Data

A DataHub script has complete access to all the data in the DataHub. Every point in the DataHub is available in Gamma as a global variable, with the syntax:

$domain_name:point_name

The dollar sign character ($) tells Gamma that the colon is part of the variable name. A colon in Gamma is normally a syntactic element and can't be used in a variable name. However, the DataHub uses a colon (:) in point names to separate the domain name from the rest of the point name. So we need to use the dollar sign. The dollar sign is not part of the variable name.

[Note]

For these examples, ensure that the DataSim program is running and connected to the DataHub.

Access a Value Once

To start with, here's how to read a value one time.

  1. Create a new script with a class named AccessData, selecting Allow only one instance. Here's how.
  2. Scroll down to the .constructor method, and enter the following:
    method AccessData.constructor ()
    {
        princ("The sine is: ", $DataSim:Sine, "\n");
    }
  3. Make sure the DataSim program is running, and that the Script Log is open so you'll be able to see the script output.
  4. Click the blue arrow icon in the Script Editor toolbar. You should see a value appear in the Script Log window, like this:
  5. Click the blue arrow icon several more times. Each time, a new value should appear in the Script Log. The values will differ because the value for the sine wave in DataSim is constantly changing.

Access Values Continuously

Getting a single value from the DataHub is fine, but we can do much better. Let's print each new value from a point every time it changes.

  1. First you should move the princ statement out of the .constructor. This may seem trivial in this example, but it is a good habit to get into. Move the princ statement to the AccessData.sample method, and edit the method name and princ statement to look like this:
    method AccessData.print_point (pt)
    {
        princ("The sine is: ", pt, "\n");
    }
  2. Edit the .constructor method like this:
    method AccessData.constructor ()
    {
        .OnChange(#$DataSim:Sine,
                  `(@self).print_point($DataSim:Sine));
    }
    The OnChange method is inherited from the parent class, Application. This method is a wrapper for the on_change function, which tells Gamma to evaluate an expression when a given symbol changes value. In this case, the symbol is $DataSim:Sine and the expression is our print_point function. The first expression is protected from evaluation by the # quote operator.
    The second expression is also quoted so that it doesn't run until the point actually changes. However, the self that is usually understood must be explicitly written and evaluated so that Gamma knows what the .print_point method applies to. Therefore, we use the ` and @ quote operators.
  3. Click the blue arrow icon in the Script Editor toolbar.
    A new value gets written twice a second. To see it really fly, bring up the DataSim window, click the More button, and change the Update Frequency to 200 (don't forget to click Apply Changes). To make it stop, click DataSim's Pause button.
    But what if you can't stop the data flow? How do you get the princ function to stop?

Stop Accessing Values

Often you will want a script's change functions to stop when the class instance is destroyed. Conveniently, the Application class has a destructor that runs any time a child class gets destroyed, and which removes all OnChange functions. One way to destroy the instance of class is with a timer.

[Note]

The timer is used here for demonstration purposes. Most Windows programs get destroyed by clicking a button or some other means.

  1. Go to .constructor method and adding the following code:
    after(3, `destroy(@self));
    This uses Gamma's after timer function, which in this case will activate 3 seconds after the instance is constructed and cause the instance to destroy itself. Again, to prevent the destroy function from being evaluated and destroying our instance prematurely, we have to quote it. And again, we use the ` and @ quote operators to evaluate the self argument. After 3 seconds, the destroy function will be evaluated, and the instance gets destroyed.
  2. Your two methods should now look like this:
    method AccessData.print_point (pt)
    {
        princ("The sine is: ", pt, "\n");
    }
    
    method AccessData.constructor ()
    {
        .OnChange(#$DataSim:Sine,
                  `(@self).print_point($DataSim:Sine));
        after(3, `destroy(@self));
    }
  3. Run the script. You should see output in the Script Log for 3 seconds, then nothing.

Verify Results

  1. To verify that the instance of the class has been destroyed, type instance_p(_AccessData_Singleton) in the text entry field at the bottom of the Script Log and press Enter. The output should look like this:
    --> instance_p(_AccessData_Singleton);
    nil
    The instance_p function is a Gamma predicate that checks to see if accessdata is an instance. Gamma returns nil, indicating that it is not an instance.
  2. Since accessdata was an instance and is no more, it is probably a destroyed instance. To check, type destroyed_p(_AccessData_Singleton); and press Enter. The output should look like this:
    --> destroyed_p(_AccessData_Singleton);
    t
    Gamma returns t, indicating that it is a destroyed instance.