Code-based Rules

More complex scenarios, which are currently not supported by the graphical view can be implemented via the code editor in the Scala programming language. Similar to Mappings via drag and drop, there is no knowledge of the underlying communication protocol (e.g., MQTT, OPCUA, etc.) needed. Protocols are hidden behind the corresponding Information Models.

Basics - Rule construct

A Rule is always starting with a Trigger (1). The Trigger can represent a Variable, an Event or a Command; within one of the selected Information Models. After the trigger call mapTo (2) and define the function body by adding curly braces (3). Depending on the Trigger declare the TriggerInstance (4). Depending on the type of the Trigger use the naming accordingly:

RuleConstruct

The Source (5) is the content of the TriggerInstance (e.g., In case the Trigger is a Variable, then is the Source an Instance of that Variable) In order to assign the Source to the Target, add the := operator (6). The Target can be any variable you want to map to (7).

RuleConstruct

Variable to Event Mapping

In this case the mapping of the Complex Variable CurrentOrder in the EquipmentModel and of a Simple Variable in the EnterpriseModel to the EquipmentNewOrderStart Event in the MesModel is described.

  • Trigger: EquipmentModel.StartNewOrderFlag (line 1)

  • TriggerInstance of EquipmentModel.Alarm: variable (line 1)

  • Since values are assigned to an Event, call the function - send, on the EquipmentNewOrderStartEvent (line 2) and define the TriggerInstance - event (line 2).

  • The Targets are defined by entering the path of the variables in the event - event.EquipmentId (line 4).

Rule - StartOrder - Variable/Event
 1 EquipmentModel.Alarm mapTo {variable =>
 2    MesModel.EquipmentAlarm.send(event => {
 3      Try {
 4        event.EquipmentId := EnterpriseModel.EquipmentName
 5        event.OrderNr := EquipmentModel.CurrentOrder.OrderNr
 6        event.MaterialID := EquipmentModel.CurrentMaterialID
 7        event.AlarmInfo := EquipmentModel.AlarmInfo
 8        CommunicationLogger.log(variable, event)
 9      }
10    })
11 }

Event to Variable Mapping

In this case the mapping of values inside the TransferNewOrder Event from the MesModel into variables from the EquipmentModel is described.

  • The Trigger is defined by entering the path of the Event - MesModel.TransferNewOrder (line 1). Since an Event is used as Trigger, the TriggerInstance is named accordingly - event (line 1).

  • In the function body provide the Complex Variable NewOrder and the Simple Variable NewMESOrderFlag with data from the MesModels TransferNewOrder Event.

  • Targets are defined by entering the path of the variables like - EquipmentModel.NewOrder.OrderNr (line 3).

  • In order to assign values to OrderNr, MaterialNr and Quantity of the Complex Variable NewOrder, enter the TriggerInstance event followed by the variable name of the TransferNewOrder Event - event.OrderNr (line 3).

  • In this case it is also possible to provide the variable NewMesOrderFlag with a Boolean like - true (line 6).

Rule - TransferNewOrder - Event/Variable
1 MesModel.TransferNewOrder mapTo { event =>
2    Try {
3      EquipmentModel.NewOrder.OrderNr := event.OrderNr
4      EquipmentModel.NewOrder.MaterialNr := event.MaterialNr
5      EquipmentModel.NewOrder.Quantity := event.Quantity
6      EquipmentModel.NewMESOrderFlag := true
7    }
8  }

Commands Mapping

The following scenario describes a Rule mapping incoming data from a file to MQTT. When the FileEvent is triggered - the rule executes first the DatabaseCommand to retrieve data from a database.

  • Trigger is defined by entering the path of the Event - file.FileEvent (line 1). Since an Event is used as Trigger, the TriggerInstance should be named accordingly - event (line 1).

  • Inside the function body execute a Command. The execution of a Command is defined by entering the path of the Command. At the end of the path, call the execute function (line 2). The TriggerInstance is named accordingly - command (line 4).

  • The lines 4-6 show the first part of the Command. Here assign values from the source model to the Command Parameters.

  • Since every Command has a Reply, we need to define the reply section - (line 8).

  • In this case send out the data over MQTT after the data is retrieved from the database. In the reply function body, enter the path of the MqttEvent. Since this is the 2nd Event, the TriggerInstance can be named - event1 (line 1).

  • Inside the function body assign values from the FileEvent (line 11-13) as well as from the Reply (line 14-15) to the MqttEvent.

Rule - File2MqttWithDB - Event/Commands
 1  file.FileEvent mapTo {event =>
 2    database.DatabaseCommand.execute(command => {
 3      Try {
 4        command.orderNr := event.orderNr
 5        command.materialNr := event.materialNr
 6        CommunicationLogger.log(event, command)
 7      }
 8    }, reply => {
 9      mqtt.MqttEvent.send(event1 => {
10        Try {
11          event1.Quality := event.quality
12          event1.OrderNr := event.orderNr
13          event1.MaterialNr := event.materialNr
14          event1.Customer := reply.customer
15          event1.Product := reply.product
16          CommunicationLogger.log(reply, event1)
17          }
18      })
19    })
20  }

Mapping with Lists

The following scenario describes a Rule that is mapping incoming data from a file to MQTT. The MQTT Model contains a List called DataList. Note that lists can only be mapped in the code view.

  • Create a variable listItem that holds a reference of a newItem in the DataList (line 6)

  • Call the variable from the listItem and assign the value from the file event (line 8)

Rule - FileToMQTT - Lists
 1 csv.FileEvent mapTo { event =>
 2 
 3      event.items.foreach { item =>
 4        mqtt.MqttEvent.send(event1 => {
 5          Try {
 6            val listItem = event1.DataList.newItem
 7 
 8            listItem.Timestamp := item.Timestamp
 9            listItem.Pressure := item.Alarmlevel
10 
11            CommunicationLogger.log(event, event1)
12          }
13        })
14      }
15  }

Logging

Logging can be added in the Rule implementation by calling - CommunicationLogger.log (line 5)

Rule with Logging
1 EquipmentModel.Alarm mapTo {variable =>
2    MesModel.EquipmentAlarm.send(event => {
3      Try {
4        event.EquipmentId := EnterpriseModel.EquipmentName
5        CommunicationLogger.log(variable, event)
6      }
7    })
8 }

Compiling

You can compile the code for the selected Rule by clicking the “Compile” button (1) and check for compilation errors before saving the Rule.

CompileCode