Working with the DemoData Example

This section discusses the Lua scripting aspect of the DemoData Example configured in the previous chapter. To learn the basics about how to use DataStudio, its displays and visualization possibilities refer to the DataStudio documentation here. The DemoData Example illustrates different use cases of Lua scripting, such as Lua libraries, event based script execution, object references and model actions.

Demo Data Using a Script Library

The general purpose of this example is to provide objects that create data similar to a real process. The DemoData contains ten GenericItems that are configured individually to match the physical entity they are representing.

Simulated Density
Figure 1. Simulated Density

There are two objects for simulation of density (D), flow (F), pressure (P), quality (Q), and temperature (T), with different Generation Periods and Limit Settings. Although the main objective of this example is not the Lua script that calculates the simulation data, it is a good show case of how libraries can be used in the Lua scripting engine.

Objects with Scripts Using a Script Library

The Lua Script Body of the simulation objects are identical.

local libHelpers = require("SampleHelpers")
return libHelpers.GetNextRandomValue(syslib.getselfpath(), nil)

Firstly, the library SampleHelper is embedded into the script. Then it calls the GetNextRandomValue function from the embedded library whose returned value becomes the new current value of the object. The library is located in one of the predecessor tree nodes, in this case it is hosted by the Examples folder.

Folder with Script Libraries
Figure 2. Folder with Script Libraries

Script libraries can be hosted by different objects, and are available to all descendants in the tree hierarchy. As you can see in the first line of the script, the embedding call require uses the Script Library Id to refer to the library that will be embedded.

Although it is recommended for consistency to keep _Script Library Id_s unique, this is not mandatory. A script will search for the ID specified in the require command upwards the tree, and use the first library that matches it.

Lua Library Syntax

A Lua library follows a certain syntax that describes the functions (and/or variables) that are provided by it.

SimpleMathLib = {
    Add = function(a,b)
    return a+b
    end,
    Subtract =function(a,b)
    return a-b
    end
}
return SimpleMathLib

The above example declares two functions called Add and Subtract, that each take two parameters, and perform a simple math operation with those two. Note how the Add and Subtract functions are separated with a comma from each other, and how the script returns the library.

Event Based Script Calculation

The DemoData Example also provides some objects that run scripts based on events triggered by the value change of other objects. Using the Lua scripting engine, data from sources in remote locations can be read and processed regardless of the system they are running. Processed data can then be written to any selected object (for instance to an operational control center system) in another remote location. In the DataDemo example, an object reads data from two different data sources, using them as inputs to perform a calculation. Data is then written to a target object with the value written depending on the outcome of the calculation.

Average Quality Check Script
Figure 3. Average Quality Check Script

Looking at the script of the object 'Average Quality Check', we can see that:

  1. It is of the type ActionItem, meaning it is executed on an event based trigger, not periodically.

  2. It uses one passive object references (DI_Out), that is used to simplify the script code (highlighted by the yellow boxes).

  3. It uses two triggering object references, both causing the script to run whenever they change value, quality, timestamp or any property (highlighted by the orange boxes).

The script returns a string value (the avQ value plus a quality indication) and writes a binary value to the passively linked Q_LOW data holder object.

Note in the script how the script uses the object references' names in the code when using the functions getvalue and setvalue of the system’s Lua extension. For more details about how to create references, refer to the DataStudio documentation.

Create History

The ProcessData GenItems in the DemoData example generate random values using the GetNextRandomValue function from the SampleHelpers script library in the Examples folder. We use this function again, alongside the syslib.sethistory function to create a year’s worth of historical data for the ProcessData items. With this historical data you can start to use the HistoryGrid and HistoryTrend displays in DataStudio. The CreateHistory ActionItem that runs the Lua script to create the historical data can be found in the Logic Folder in the DemoData Node.

Logic Folder - Create History
Figure 4. Logic Folder - Create History

Select the CreateHistory ActionItem and open the embedded Lua script. The script sets the time to start the history. In this case it is a year prior to the current time in milliseconds (variable old) and the variable step sets the time interval between each written history data point to 1 min or 60000 ms. The for loop calls the get_children_paths function in the SampleHelpers library to cycle through each simulation item in the ProcessData folder. The History values are then set by stepping through each time point from old to now with a time interval of 1 min between points. The first value is calculated from the limit values of the ProcessData item, then new random values are calculated from the last set value by again using the GetNextRandomValueFunction in the SampleHelpers library. The script then disables the CreateHistory item to prevent accidental re-execution of the script. Open a HistoryTrend display for one of the items and select Entire Data to see that the History was set for time period has been set.

HistoryTrend for ProcessData Item
Figure 5. HistoryTrend for ProcessData Item

Create KPI Model

The DemoData example creates a set of simulation items in the I/O model including items that make calculations when new data is produced. So far, all the items described (including Lua scripts and script libraries) were created in the I/O model using the MassConfig display. For the KPI model the items are instead created using Lua scripting.

Objects can be created in any of the models using either MassConfig, Lua scripting or the external API to make SCI calls. You can also create objects manually using the Create wizard in DataStudio.

Select the CreateKPIModel ActionItem in the I/O Model tree (it is in the same Logic folder as the CreateHistory item) and open the Lua script body by clicking on "…" in the object properties panel.

CreateKPIModel ActionItem
Figure 6. CreateKPIModel ActionItem

The first part of the script embeds the KpiHelpers library in the script using the require call. The KpiHelpers library is held as a script library in the Examples folder like the Sample. Helpers library described in an earlier section. The paths to the folders in the I/O tree hierarchy are then set using the syslib.getparentpath and syslib.getobject commands. Because the script is being executed by the CreateKPIModel object then the paths to these folders are all relative to to its position in the tree.

The first objects are created in the KPI model, starting with the top-level Enterprise object (More information about KPI Model objects is available here). The call of the obj:children() method on the ProcessData folder object returns all its children as Lua table. The KPI objects are created using the createGroup function in the KpiHelpers script library that takes object name, class and parent path as arguments. The function first checks if the object already exists before creating the object.

To create an Enterprise object in the KPI model, the root path for the KPI Model - "/" is used (see the 'grp' variable definition using the syslib.getobject() call in the Create KPI Model script).

The second part of the CreateKPIModel script cycles through the returned table of ProcessData items and creates GenKPI items in the KPI Model accordingly. The ProcessData simulation items belong to either Reactor 4711 or Reactor 666 and we create "Plant" objects in the KPI model to order the KPI items in terms of location. Under each reactor the KPIs are arranged into either "Measurements" or "LabData" dependent on the object name being a Density(D), Pressure(P), Flow(F), Quality(Q) or Temperature(T) measurement (using the Lua string.sub function, the first letter of the object name object name is identified). The "Measurements" and "LabData" folders are created followed by the GenKPIs which are linked to the appropriate simulation item in the I/O Model. Functions in the KpiHelpers script library are used to create the objects and set the properties.

After executing the script, the CreateKPIModel object disables itself to prevent accidental re-execution. View the KPI Model to see the created objects and KPI structure.

KPI Model
Figure 7. KPI Model