In general scripts are attached to objects that exist in the different models of system:inmation. Technically speaking, scripts are hosted by properties of objects. Depending on the object type, the property that hosts the script can be different, and the effect of setting it can have a different outcome.
|Because scripts reside in object properties, they can be read and written like any other property, including access from external interfaces like .NET API!|
Some object types are able to execute scripts while others can only store them. The latter type is used to store scripts in higher tree levels, so that their successors (children in tree) can access and make use of them. Such scripts are stored as Lua script libraries.
The object types that can execute scripts are:
- I/O Model
GenericItem This object type is used to generate data on a periodical basis. It can generate data in various ways, including a Lua script execution.
ActionItems This object type is used to execute a script on an event trigger. Various triggers can be defined. The most common one being another object changing its value.
Rule The Rule object type can be used during automatic object discovery to make changes to the discovered object while it is being created in system:inmation. One action type of a rule is the execution of a Lua script.
The object types that can keep script libraries are:
- I/O Model
System The tree’s top level object. Libraries setup here are available to all objects in the whole system.
Core Libraries setup here are available to all objects below the particular Core object.
Connector Libraries setup here are available to all objects below the particular Connector object.
Datasource Libraries setup here are available to all objects below the particular Datasource object.
I/O Node Libraries setup here are available to all objects below the particular I/O Node object.
Folder Libraries setup here are available to all objects below the particular Folder object.
In addition, the scripting engine was extended by a Lua library that allows you to work with
system:inmation models, objects and their properties. Functions in the
syslib library can be used to
create, update, or delete objects. For a detailed description of the inmation Lua extension, please refer to the Lua Scripting in the System Documentation and the Lua API docs.
As a first step into the Lua scripting environment, we will create a very simple calculation to be executed by the Core. This will be done in 3 steps. First we will prepare a location in the object tree to host the objects we need for this example. In the second step we’ll create objects that simulate data, before finally creating the first simple calculation.
To do so open DataStudio and login with administrative rights. Then go to the I/O Model tree and right click the Core object. Selectfrom the context menu.
In the Create Folder Wizard enter "Examples" in the Object Name edit box. Leave all other options as default and click the Create button.
Select the newly created folder and create a subfolder called "Lua", executing the step mentioned above. Repeat this once more to create a folder within the Lua folder named "Jump Start". You should see something like this in your DataStudio:
|The nested object hierarchy created is not required to run the script! Its only purpose is to structure the application logic, and to fit the example import (see also CHAPTER 3 on page 20).|
As a starting point, we will create two items that generate simulated data. If you already have a real data source connected to system:inmation, you can skip this step and use real data points. Right click the Jump Start folder and selectfrom the context menu.
In the Create Generic Item wizard’s Common step enter Saw Tooth in the Object Name edit box. Leave all other options default and click Next.
In the Limit Settings step, do not make any changes, and click Next In the Generation Type step, change the Function Period to 30000 and click Next.
In the Archive Options step, change the Archive Selection to Production Archive and check the Raw History option. Now click Create to create this object in the tree.
Now create a second simulation item. Right click the Jump Start folder and selectfrom the context menu to start the Object Creation wizard again. In the Create Generic Item wizard’s Common step enter Sinus in the Object Name edit box. Leave all other options default and click Next.
In the Limit Settings step, do not make any changes, and click Next. In the Generation Type step, change Function to Sine wave values and the Function Period to 30000. Now click Next.
In the Archive Options step, change the Archive Selection to Production Archive and check the Raw History option. Now click the Create button to create this object in the tree.
You should see something like this in the I/O Model panel of DataStudio:
In this step we will create another GenericItem, that executes a script making a simple addition calculation periodically. Right click the Jump Start folder and select Admin; New; Generic Item from the context menu. In the Create Generic Item Wizard’s Common step, enter Simple Calc in the Object Name edit box, and select 5000 ms as Generation Period. Now click Next.
Leave the Limit Settings step as default, and click Next. In the Generation Type step, select the Lua Script Data Generator option, and then click the … button to open the Lua Script Body Editor. Enter the following code into the script editor:
function calc() -- get the values of the two simulation items local sin = syslib.getvalue("/System/MasterCore/Examples/Lua/Jump Start/Sinus") local saw = syslib.getvalue("/System/MasterCore/Examples/Lua/Jump Start/Saw Tooth") -- return the sum of the values return sin + saw end -- return the result of the calculation -- it becomes the current value of the calculation return calc()
You can see that the editor highlights the Lua syntax in different colors (keywords in blue, comments in green, and strings, including
paths in red). Also used in this script is the system extension to the Lua environment. Here the
is called to read a value from an object by using the object’s path in the object tree. The script editor also gives support
while you are coding through the LuaSense feature, making suggestions and providing useful explanations of
functions, as you type.
To view the LuaSense suggestions at a particular point in already written code, move the blinking cursor to the required position and press Ctrl+Space to open the information display. The LuaSense feature can also be toggled on/off using the icon in the menu bar of the script editor. After writing the script click Ok to close the editor, then click the Next button. In the Archive Options step, change the Archive Selection to Production Archive and check the Raw History option. Now click the Create button to create this object in the tree.
The I/O Model panel and the object properties panel for Simple Calc should now look something like the following:
Note how the calculation is executed every 5000 milliseconds (as was configured during creation of the object), independently of the inputs from the Saw Tooth and Sinus objects that change every 1000 milliseconds (as was configured during their creation). If you add the Saw Tooth, Sinus and Simple Calc objects to a RealTimeGrid display (see DataStudio documentation for more details) the different execution times can be observed concurrently, as the respective object values update. An example how to execute a script based on an input data change can be found in CHAPTER 4.
Lua scripts that run into an error during execution will return their error as the current value of the item hosting the script. As an example, open a Script Editor in DataStudio via themenu. Then drag & drop the Simple Calc object (created in 2.4.3 Step 3: Periodical Calculation on page 12) from the I/O Model tree into the editor. In the icon menu at the top of the Script Editor display, click this Show Watch Items icon, to display the Watch Items area.
The watch item will be shown in the Script Editor display below the programming area.
Note that the script item itself is automatically added to the list. Add more items from the I/O Model tree to the watch item list using drag & drop. For example, add the Saw Tooth and Sinus objects that are the inputs for the Simple Calc calculation:
To see how the error handling works, we will create an error in the script. For example, remove the plus sign from line 6. Then click the Update Object icon to apply the change.
This creates a syntax error in the script.
Note that A) The script editor identifies the syntax error and highlights the section of the code with a red curly underline B) The item’s value becomes the error message, with information about which line is causing the error ("@6") and what the error is. C) The item’s quality turns Bad (red dot by the object in the marked items area and in the I/O model panel)
The ability to have scripts housed at various levels of the I/O model (in particular having scripts at the Core and the Connector level), means the scripts can be executed by different components running on different physically distributed hosts (for instance, a Core in the headquarters, or Connectors in remote locations). Basically this means that a script residing on the Core level is actually executed by the Core service, while a script residing on the Connector level is actually executed by the Connector service. This distributed computation approach has an impact on the execution possibilities of each script, and when these scripts can execute. Clearly a script on the Connector level can no longer be executed when the Connector service is shut down. On the other hand, it can be executed independently from an active connection to the Core service. The same applies to scripts on Core level, which can run independently of any connected Connector. This ability comes with the limitation that the Connector can only work with objects, and their values, that belong to the Connector’s model tree hierarchy, meaning objects that are successors of the Connector object in the I/O model. The Core however, can operate on all objects, including ones of various Connectors, because they are all successors of the Core object. In addition, the Core can also operate across the different models, that logically reside in the Core. This means a Lua script on Core level can make changes to multiple models at the same time (e.g. create new objects in the I/O model and KPI model, and link them).
The Lua script engine is embedded in the backend services of system:inmation. Therefore, all execution of scripts happens on the server side. This allows the complete server side CPU power of all participating machines within system:inmation to be used, but also requires that users create scripts in a responsible way. The real time engine of the backend services also executes scripts in real time on shared resources. Should a script cause a very high memory allocation, or CPU load, this can have a negative impact on the backend service executing it! This has particular relevance for scripts that run for a time longer than a second (for example when scripts query data from some other data source like a SQL database). In these cases, it is strongly advised that they are run on a dedicated thread. To configure this, check the Dedicated Thread Execution property of the script:
However, it does not make sense to run all scripts on a dedicated thread as a high number of threads can also slow down a backend service (depending on the available hardware). Because of this it is important to balance the number of scripts running on dedicated threads with the ones running on shared resources. Should you run into the situation where many scripts (1000+) have to execute the same long running code, we recommend that you create a single script running on a dedicated thread, that can deal with a queue of executions within the script environment.