Table of Contents
eTrice provides an implementation of the ROOM modeling language (Real Time Object Oriented Modeling) together with editors, code generators for Java, C++ and C code and exemplary target middleware.
The model is defined in textual form (Xtext) with graphical editors (Graphiti) for the structural and behavioral (i.e. state machine) parts.
Basically everyone who develops eventdriven realtime or embedded systems.
If you have other ideas how to use it, tell us!
This chapter will give a rough overview of what ROOM ( R eal time O bject O riented M odeling) is and what it is good for. It will try to answer the following questions:
Where does it come from?
Which kind of SW-Systems will be addressed?
What is the relation between OOP and ROOM?
What are the benefits of ROOM?
Which consequences must be taken into account?
Room was developed in the 1990th on the background of the upcoming mobile applications with the goal to manage the complexity of such huge SW-Systems. From the very beginning ROOM has focused on a certain type of SW-Systems and is, in contrast to the UML, well suited for this kind of systems. In this sense, ROOM is a DSL (Domain Specific Language) for distributed, event driven, real time systems.
Bran Selic, Garth Gullekson and Paul T. Ward have published the concepts 1994 in the book „REAL-TIME OBJECT-ORIENTED MODELING”. The company [object time] ™ developed a ROOM tool which was taken over by [Rational SW] ™ and later on by [IBM] ™. The company [Protos Software Gmbh] ™ also developed a ROOM tool called [Trice] ™ for control software for production machines and automotive systems. [Trice] ™ is the predecessor of eTrice (see Introduction to eTrice).
From our point of view ROOM provides still the clearest, simplest, most complete and best suited modeling concepts for the real time domain. All later proposals like the UML do not fit as well to this kind of problems.
As mentioned before ROOM addresses distributed, event driven, real time systems. But what is a „real time system”? ROOM defines a set of properties which are typical for a real time system. These properties are:
Timeliness
Dynamic internal structure
Reactiveness
Concurrency
Distribution
Reliability
Each of these properties has potential to make SW development complex. If a given system can be characterized with a combination of or all of these properties, ROOM might be applied to such a system.
As an example take a look at a washing machine. The system has to react on user interactions, has to handle some error conditions like a closed water tap or a defective lye pump. It has to react simultaneously to all these inputs. It has to close the water valve in a certain time to avoid flooding the basement. So, the system can be characterized as timely, concurrent and reactive. As long as the washing machine does not transform to a laundry drier by itself, the system has no dynamic internal structure and as long as all functions are running on a single micro controller the (SW)-system is not distributed. ROOM fits perfect to such a system.
A SW system which mainly consists of data transformations like signal/image processing or a loop controller (e.g. a PID controller) cannot be characterized with any of the above mentioned properties. However, in the real world most of the SW systems will be a combination of both. ROOM can be combined with such systems, so that for example an actor provides a [run to completion] context for calculating an image processing algorithm or a PID controller.
The relation between classical object oriented programming and ROOM is comparable to the relation between assembler programming and C programming. It provides a shift of the object paradigm. As the picture shows, the classic object paradigm provides some kind of information hiding. Attributes can be accessed via access methods. Logical higher level methods provide the requested behavior to the user.

As the figure illustrates, the classical object paradigm does not care about concurrency issues. The threads of control will be provided by the underlying operating system and the user is responsible to avoid access violations by using those operating system mechanisms directly (semaphore, mutex).

ROOM provides the concept of a logical machine (called actor) with its own thread of control. It provides some kind of cooperative communication infrastructure with „run to completion” semantic. That makes developing of business logic easy and safe (see basic concepts). The logical machine provides an encapsulation shell including concurrency issues (see chapter „Run to completion”).

This thinking of an object is much more general than the classic one.
ROOM has a lot of benefits and it depends on the users point of view which is the most important one. From a general point of view the most important benefit is, that ROOM allows to create SW systems very efficient, robust and safe due to the fact that it provides some abstract, high level modeling concepts combined with code generation and a small efficient runtime environment.
In detail:
ROOM models contain well defined interfaces (protocols), which makes it easy to reuse components in different applications or e.g. in a test harness.
Graphical modeling makes it easy to understand, maintain and share code with other developers
Higher abstraction in combination with automated code generation provides very efficient mechanisms to the developer.
ROOM provides graphical model execution, which makes it easy to understand the application or find defects in a very early phase.
Generating code from models will introduce some overhead in terms of memory footprint as well as performance. For most systems the overhead will be negligible. However, the decision for using ROOM should be made explicitly and it is always a trade off between development costs, time to market and costs in terms of a little bit more of memory and performance. Thanks to the powerful component model, ROOM is especially well suited for the development of software product lines with their need for reusable core assets.
Care must be taken during the introduction of the new methodology. Due to the fact that ROOM provides a shift of the object paradigm, developers and teams need a phase of adaption. Every benefit comes at a price.
TODO: Screenshot of Actor with Port and another with a Protocol
The basic elements of ROOM are the actors with their ports and protocols. The protocol provides a formal interface description. The port is an interaction point where the actor interacts with its outside world. Each port has exactly one protocol attached. The sum of all ports builds up the complete interface of an actor. Each port can receive messages, with or without data, which are defined in the attached protocol. Each message will be handled by the actors behavior (state machine) or will be delegated to the actors internal structure.
The actor provides access protection for its own attributes (including complex types (classical objects)), including concurrency protection. An actor has neither public attributes nor public operations. The only interaction with the outside world takes place via interface ports. This ensures a high degree of reusability on actor level and provides an effective and safe programming model to the developer.
Receiving a message via a port will trigger the internal state machine. A transition will be executed depending on the message and the current state. Within this transition, detail level code will be executed and response messages can be sent.
With this model, a complex behavior can be divided into many relatively simple, linked actors. To put it the other way round: The complex behavior will be provided by a network of relatively simple components which are communicating with each other via well defined interfaces.
ROOM provides two types of hierarchy. Behavioral hierarchy and structural hierarchy. Structural hierarchy means that actors can be nested to arbitrary depth. Usually you will add more and more details to your application with each nesting level. That means you can focus yourself on any level of abstraction with always the same element, the actor. Structural hierarchy provides a powerful mechanism to divide your problem in smaller pieces, so that you can focus on the level of abstraction you want to work on.
The actor’s behavior will be described with a state machine. A state in turn may contain sub states. This is another possibility to focus on an abstraction level. Take the simple FSM from the blinky actor from the blinky tutorial.
Top level:

[blinking] Sub machine:

From an abstract point of view there is a state „blinking”. But a simple LED is not able to blink autonomously. Therefore you have to add more details to your model to make a LED blinking, but for the current work it is not of interest how the blinking is realized. This will be done in the next lower level of the hierarchy.
This simple example might give an idea how powerful this mechanisms is.
The hierarchical FSM provides a rich tool box to describe real world problems (see „room concepts”).
Layering is another well known form of abstraction to reduce complexity in the structure of systems. ROOM is probably the only language that supports Layering directly as language feature. Layering can be expressed in ROOM by Actors with specialized Ports, called Service Access Points ( SAP) and Service Provision Points ( SPP).
TODO: Screenshot of Timing Service
The Actor that provides a service implements an SPP and the client of that service implements an SAP. The Layer Connection connects all SAPs of a specific Protocol within an Actor hierarchy with an SPP that implements the service.
From the Actors point of view, SAP and SPP behave almost like regular ports.
„Run to completion” (RTC) is a very central concept of ROOM. It enables the developer to concentrate on the functional aspects of the system. The developer doesn’t have to care about concurrency issues all the time. This job is concentrated to the system designer in a very flexible way. What does „run to completion” mean: RTC means that an actor, which is processing a message, can not receive the next message as long as the processing of the current message has been finished. Receiving of the next message will be queued from the underlying run time system.
Note: It is very important not to confuse run to completion and preemption. Run to completion means that an actor will finish the processing of a message before he can receive a new one (regardless of its priority). That does not mean that an actor cannot be preempted from an higher priority thread of control. But even a message from this higher prior thread of control will be queued until the current processing has been finished.
With this mechanism all actor internal attributes and data structures are protected. Due to the fact that multiple actors share one thread of control, all objects are protected which are accessed from one thread of control but multiple actors. This provides the possibility to decompose complex functionality to several actors without the risk to produce access violations or dead locks.
Since from ROOM models executable code can be generated, it is important to define the way the actors are executed and communicate with each other. The combination of communication and execution is called the Execution Model. Currently the eTrice tooling only supports the message driven and parts of the data driven execution model. In future releases more execution models will be supported, depending on the requirements of the community.
message driven (asynchronous, non blocking, no return value): Usually the message driven communication is implemented with message queues. Message queues are inherently asynchronous and enable a very good decoupling of the communicating parties.
data driven (asynchronous, non blocking, no return value): In data driven communication sender and receiver often have a shared block of data. The sender writes the data and the receiver polls the data.
function call (synchronous, blocking, return value): Regular function call as known in most programming languages.
execution by receive event: The message queue or the event dispatcher calls a „receive event” function of the message receiver an thereby executes the processing of the event.
polled execution: The objects are processed by a cyclic „execute” call
execution by function call: The caller executes the called object via function call
In todays software systems in most cases one or several of the following execution models are used:
The message driven execution model is a combination of message driven communication and execution by receive event. This model allows for distributed systems with a very high throughput. It can be deterministic but the determinism is hard to proof. This execution model is often found in telecommunication systems and high performance automation control systems.
The data driven execution model is a combination of data driven communication and polled execution. This model is highly deterministic and very robust, but the polling creates a huge performance overhead. The determinism is easy to proof (simple mathematics). The execution model is also compatible with the execution model of control software generated by Tools like Matlab™ and LabView™. This model is usually used for systems with requirements for safety, such as automotive and avionic systems.
The synchronous execution model could also be called „simple function calls”. This model is in general not very well suited to support the „run to completion” semantic typical for ROOM models, but could also be generated from ROOM models. With this execution model also lower levels of a software system, such as device drivers, could be generated from ROOM models.
ETrice generates code out of ROOM models. The code generator and the generated code relies on a runtime framework and on some ready to use model parts. This parts provide services like:
messaging
logging
timing
Additionally some tutorial models will be provided to make it easy to start with eTrice. All this parts must be available in our workspace before you can start working. After installation of eclipse (indigo) and the eTrice plug in your workspace should look like this:

Just the [eTrice] menu item is visible from the eTrice tool. From the [File] menu select [File->New->Project]

Open the [eTrice] tab and select [eTrice Java ModelLib]
Press [Next] and [Finish] to install the Modellib into your workspace.

Do the same steps for [eTrice Java Runtime] and [eTrice Java Tutorials]. The resulting workspace should look like this:

Now workspace is set up and you can perform the tutorials or start with your work.
The tutorial models are available in the [org.eclipse.etrice.tutorials] project. All tutorials are ready to generate and run without any changes. To start the code generator simply run [gen_org.eclipse.etrice.tutorials.launch] as [gen_org.eclipse.etrice.tutorials.launch]:

After generation for each tutorial a java file called [SubSystem_ModelnameRunner.java] is generated. To run the model simply run this file as a java application:

To stop the application type „quit” in the console window.

Performing the tutorials will setup an dedicated project for each tutorial. Therefore there are some slight changes especially whenever a path must be set (e.g. to the model library) within your own projects. All this is described in the tutorials.
In this tutorial you will build your first very simple eTrice model. The goal is to learn the work flow of eTrice and to understand a few basic features of ROOM. You will perform the following steps:
create a new model from scratch
add a very simple state machine to an actor
generate the source code
run the model
open the message sequence chart
Make sure that you have set up the workspace as described in [Setting up the workspace].
The easiest way to create a new eTrice Project is to use the eclipse project wizard. From the eclipse file menu select [File->New->Project] and create a new eTrice project and name it [HelloWorld]

The wizard creates everything that is needed to create, build and run an eTrice model. The resulting project should look like this:

Within the model directory the model file [HelloWorld.room] was created. Open the [HelloWorld.room] file and delete the contents of the file. Open the content assist with Ctrl+Space and select [model skeleton].

Edit the template variables by typing the new names and jumping with Tab from name to name.
The resulting model code should look like this:
RoomModel HelloWorld {
LogicalSystem System_HelloWorld {
SubSystemRef subsystem : SubSystem_HelloWorld
}
SubSystemClass SubSystem_HelloWorld {
ActorRef application : HelloWorldTop
}
ActorClass HelloWorldTop {
}
}
The goal of eTrice is to describe distributed systems on a logical level. In the current version not all elements will be supported. But as prerequisite for further versions the following elements are mandatory for an eTrice model:
the [LogicalSystem]
at least one [SubSystemClass]
at least one [ActorClass]
The [LogicalSystem] represents the complete distributed system and contains at least one [SubSystemRef]. The [SubSystemClass] represents an address space and contains at least one [ActorRef]. The [ActorClass] is the building block of which an application will be built of. It is in general a good idea to define a top level actor that can be used as reference within the subsystem.
The outline view of the textual ROOM editor shows the main modeling elements in an easy to navigate tree.

We will implement the Hello World code on the initial transition of the [HelloWorldTop] actor. Therefore open the state machine editor by right clicking the [HelloWorldTop] actor in the outline view and select [Edit Behavior].

The state machine editor will be opened. Drag and drop an [Initial Point] from the tool box to the diagram into the top level state. Drag and drop a [State] from the tool box to the diagram. Confirm the dialogue with [ok]. Select the [Transition] in the tool box and draw the transition from the [Initial Point] to the State. Open the transition dialogue by double clicking the caption of the transition and fill in the action code.
System.out.println("Hello World !");
The result should look like this:

Save the diagram and inspect the model file. Note that the textual representation was created after saving the diagram.

Now the model is finished and source code can be generated. The project wizard has created a launch configuration that is responsible for generating the source code. From [HelloWorld/] right click [gen_HelloWorld.launch] and run it as gen_HelloWorld. All model files in the model directory will be generated.

The code will be generated to the src-gen directory. The main function will be contained in [SubSystem_HelloWorldRunner.java]. Select this file and run it as Java application.

The Hello World application starts and the string will be printed on the console window. To stop the application the user must type [quit] in the console window.

During runtime the application produced a MSC and wrote it to a file. Open HelloWorld/tmp/log/SubSystem_HelloWorld_Async.seq using Trace2UML (it is open source and can be obtained from http://trace2uml.tigris.org/). You should see something like this:

Now you have generated your first eTrice model from scratch. You can switch between diagram editor and model (.room file) and you can see what will be generated during editing and saving the diagram files. You should take a look at the generated source files to understand how the state machine is generated and the life cycle of the application. The next tutorials will deal with more complex hierarchies in structure and behavior.
This tutorial describes how to use the [TimingService], how to combine a generated model with manual code and how to model a hierarchical state machine. The idea of the tutorial is to switch a LED on and off. The behavior of the LED should be: blinking in a one second interval for 5 seconds, stop blinking for 5 seconds, blinking, stop,... For this exercise we will use a little GUI class that will be used in more sophisticated tutorials too. The GUI simulates a pedestrian traffic crossing. For now, just a simple LED simulation will be used from the GUI.
After the exercise is created you must copy the GUI to your src directory (see below).
The package contains four java classes which implements a small window with a 3-light traffic light which simulates the signals for the car traffic and a 2-light traffic light which simulates the pedestrian signals.
The GUI looks like this:

Within this tutorial we will just toggle the yellow light.
You will perform the following steps:
create a new model from scratch
define a protocol
create an actor structure
create a hierarchical state machine
use the predefined [TimingService]
combine manual code with generated code
build and run the model
open the message sequence chart
Remember exercise [HelloWorld]. Create a new eTrice project and name it [Blinky]
To use the GUI please copy the package [org.eclipse.etrice.tutorials.PedLightGUI] from „org.eclipse.etrice.tutorials/src” to your [src] directory „Blinky/src”. For this tutorial you must remove the error markers by editing the file [PedestrianLightWndNoTcp.java]. Appropriate comments are provided to remove the error marker for this turorial.
Open the [Blinky.room] file and copy the following code into the file or use content assist to create the model.
RoomModel Blinky {
LogicalSystem System_Blinky {
SubSystemRef subsystem : SubSystem_Blinky
}
SubSystemClass SubSystem_Blinky {
ActorRef application : BlinkyTop
}
ActorClass BlinkyTop {
}
}
Position the cursor outside any class definition and right click the mouse within the editor window. From the context menu select [Content Assist]

Select [ActorClass – actor class skeleton] and name it [Blinky].

Repeat the described procedure and name the new actor [BlinkyController].
With Ctrl+Shift+F you can beautify the model code.
Save the model and visit the outline view.
With the help of [Content Assist] create a [ProtocolClass] and name it [BlinkyControlProtocol]. Inside the brackets use the [Content Assist] (CTRL+Space) to create two incoming messages called [start] and [stop].
The resulting code should look like this:

With Ctrl-Shift+F or selecting [Format] from the context menu you can format the text. Note that all elements are displayed in the outline view.
Switching on and off the LED is timing controlled. The timing service is provided from the model library and must be imported before it can be used from the model.
This is the first time you use an element from the modellib. Make sure that your Java Build Path has the appropriate entry to the modellib. Otherwise the jave code, which will be generated from the modellib, can not be referenced. (right click to [Blinky] and select properties. Select the [Java Build Path] tab)

After the build path is set up return to the model and navigate the cursor at the beginning of the model and import the timing service:
RoomModel Blinky {
import room.basic.service.timing.* from "../../org.eclipse.etrice.modellib/models/TimingService.room"
LogicalSystem System_Blinky {
SubSystemRef subsystem: SubSystem_Blinky
}
...
Make sure that the path fits to your folder structure.
Now it can be used within the model. Right click to [SubSystem_Blinky] within the outline view. Select [Edit Structure]. The [application] is already referenced in the subsystem. Drag and Drop an [ActorRef] to the [SubSystem_Blinky] and name it [timingService]. From the actor class drop down list select [room.basic.service.timing.ATimingService]. Draw a [LayerConnection] from [application] to each service provision point (SPP) of the [timingService]. The resulting structure should look like this:

The current version of eTrice does not provide a graphical element for a service access point (SAP). Therefore the SAPs to access the timing service must be added in the .room file. Open the [Blinky.room] file and navigate to the [Blinky] actor. Add the following line to the structure of the actor:
SAP timer: room.basic.service.timing.PTimeout
Do the same thing for [BlinkyController].
The resulting code should look like this:

From the outline view right click to [Blinky] and select [Edit Structure]. Drag and Drop an [Interface Port] to the boarder of the [Blinky] actor. Note that an interface port is not possible inside the actor. Name the port [ControlPort] and select [BlinkyControlProtocol] from the drop down list. Uncheck [Conjugated] and [Is Relay Port]. Klick [ok]. The resulting structure should look like this:

Repeat the above steps for the [BlinkyController]. Make the port [Conjugated]
Keep in mind that the protocol defines [start] and [stop] as incoming messages. [Blinky] receives this messages and therefore [Blinky]'s [ControlPort] must be a regular port and [BlinkyController]'s [ControlPort] must be a conjugated port.
From the outline view right click [BlinkyTop] and select [Edit Structure].
Drag and Drop an [ActorRef] inside the [BlinkyTop] actor. Name it [blinky]. From the actor class drop down list select [Blinky]. Do the same for [controller]. Connect the ports via the binding tool. The resulting structure should look like this:

The application should switch on and off the LED for 5 seconds in a 1 second interval, than stop blinking for 5 seconds and start again. To implement this behavior we will implement two FSMs. One for the 1 second interval and one for the 5 second interval. The 1 second blinking should be implemented in [Blinky]. The 5 second interval should be implemented in [BlinkyController]. First implement the Controller.
Right click to [BlinkyController] and select [Edit Behavior]. Drag and Drop the [Initial Point] and two [States] into the top state. Name the states [on] and [off]. Use the [Transition] tool to draw transitions from [init] to [on] from [on] to [off] and from [off] to [on].
Open the transition dialog by double click the arrow to specify the trigger event and the action code of each transition. Note that the initial transition does not have a trigger event.
The transition dialog should look like this:

The defined ports will be generated as a member attribute of the actor class from type of the attached protocol. So, to send e message you must state [port.message(param);]. In this example [ControlPort.start()] sends the [start] message via the [ControlPort] to the outside world. Assuming that [Blinky] is connected to this port, the message will start the one second blinking FSM. It is the same thing with the [timer]. The SAP is also a port and follows the same rules. So it is clear that [timer.Start(5000);] will send the [Start] message to the timing service. The timing service will send a [timeoutTick] message back after 5000ms.
Within each transition the timer will be restarted and the appropriate message will be sent via the [ControlPort].
The resulting state machine should look like this: (Note that the arrows peak changes if the transition contains action code.)

Save the diagram and inspect the [Blinky.room] file. The [BlinkyController] should look like this:

Now we will implement [Blinky]. Due to the fact that [Blinky] interacts with the GUI class a view things must to be done in the model file.
Double click [Blinky] in the outline view to navigate to [Blinky] within the model file. Add the following code: (type it or simply copy it from the tutorial project)

[usercode1] will be generated at the beginning of the file, outside the class definition. [usercode2] will be generated within the class definition. The code imports the GUI class and instantiates the window class. Attributes for the carLights and pedLights will be declared to easily access the lights in the state machine. The Operation [destroyUser()] is a predefined operation that will be called during shutdown of the application. Within this operation, cleanup of manual coded classes can be done.
Now design the FSM of [Blinky]. Remember, as the name suggested [blinking] is a state in which the LED must be switched on and off. We will realize that by an hierarchical FSM in which the [blinking] state has two sub states.
Open the behavior diagram of [Blinky] by right clicking the [Blinky] actor in the outline view. Create two states named [blinking] and [off]. Right click to [blinking] and create a subgraph.

Create the following state machine. The trigger events between [on] and [off] are the [timeoutTick] from the [timer] port.

Create entry code for both states by right clicking the state and select [Edit State...]
Entry code of [on] is:
timer.Start(1000);
carLights.setState(TrafficLight3.YELLOW);
Entry code of [off] is:
timer.Start(1000);
carLights.setState(TrafficLight3.OFF);
Navigate to the Top level state by double clicking the [/blinking] state. Create the following state machine:

The trigger event from [off] to [blinking] is the [start] event from the [ControlPort].The trigger event from [blinking] to [off] is the [stop] event from the [ControlPort]. Note: The transition from [blinking] to [off] is a so called group transition. This is a outgoing transition from a super state (state with sub states) without specifying the concrete leave state (state without sub states). An incoming transition to a super state is called history transition.
Action code of the init transition is:
carLights = light.getCarLights();
pedLights = light.getPedLights();
carLights.setState(TrafficLight3.OFF);
pedLights.setState(TrafficLight2.OFF);
Action code from [blinking] to [off] is:
timer.Kill();
carLights.setState(TrafficLight3.OFF);
The model is complete now. You can run and debug the model as described in getting started. Have fun.
The complete model can be found in /org.eclipse.etrice.tutorials/model/Blinky.
Run the model and take a look at the generated MSCs. Inspect the generated code to understand the runtime model of eTrice. Within this tutorial you have learned how to create a hierarchical FSM with group transitions and history transitions and you have used entry code. You are now familiar with the basic features of eTrice. The further tutorials will take this knowledge as a precondition.
This tutorial shows how data will be sent in a eTrice model. Within the example you will create two actors (MrPing and MrPong). MrPong will simply loop back every data it received. MrPing will send data and verify the result.
You will perform the following steps:
create a new model from scratch
create a data class
define a protocol with attached data
create an actor structure
create two simple state machines
build and run the model
Remember exercise [HelloWorld]. Create a new eTrice project and name it [SendingData] Open the [SendingData.room] file and copy the following code into the file or use content assist to create the model.
RoomModel SendingData {
LogicalSystem SendingData_LogSystem {
SubSystemRef SendingDataAppl:SendingData_SubSystem
}
SubSystemClass SendingData_SubSystem {
ActorRef SendigDataTopRef:SendingDataTop
}
ActorClass SendingDataTop {
}
}
Position the cursor outside any class definition and right click the mouse within the editor window. From the context menu select [Content Assist] (or Ctrl+Space).

Select [DataClass – data class skeleton] and name it [DemoData]. Remove the operations and add the following Attributes:
DataClass DemoData {
Attribute int32Val: int32 = "4711"
Attribute int8Array [ 10 ]: int8 = "{1,2,3,4,5,6,7,8,9,10}"
Attribute float64Val: float64 = "0.0"
Attribute stringVal: string = "\"empty\""
}
Save the model and visit the outline view. Note that the outline view contains all data elements as defined in the model.
With the help of [Content Assist] create a [ProtocolClass] and name it [PingPongProtocol]. Create the following messages:
ProtocolClass PingPongProtocol {
incoming {
Message ping(data: DemoData)
Message pingSimple(data:int32)
}
outgoing {
Message pong(data: DemoData)
Message pongSimple(data:int32)
}
}
With the help of [Content Assist] create two new actor classes and name them [MrPing] and [MrPong]. The resulting model should look like this:
RoomModel SendingData {
LogicalSystem SendingData_LogSystem {
SubSystemRef SendingDataAppl: SendingData_SubSystem
}
SubSystemClass SendingData_SubSystem {
ActorRef SendigDataTopRef: SendingDataTop
}
ActorClass SendingDataTop { }
DataClass DemoData {
Attribute int32Val: int32 = "4711"
Attribute int8Array [ 10 ]: int8 = "{1,2,3,4,5,6,7,8,9,10}"
Attribute float64Val: float64 = "0.0"
Attribute stringVal: string = "\"empty\""
}
ProtocolClass PingPongProtocol {
incoming {
Message ping(data: DemoData)
Message pingSimple(data: int32)
}
outgoing {
Message pong(data: DemoData)
Message pongSimple(data: int32)
}
}
ActorClass MrPing {
Interface { }
Structure { }
Behavior { }
}
ActorClass MrPong {
Interface { }
Structure { }
Behavior { }
}
}
The outline view should look like this:

Save the model and visit the outline view. Within the outline view, right click on the [MrPong] actor and select [Edit Structure]. Select an [Interface Port] from the toolbox and add it to MrPong. Name the Port [PingPongPort] and select the [PingPongProtocol]

Do the same with MrPing but mark the port as [conjugated]
Within the outline view, right click MrPong and select [Edit Behavior]. Create the following state machine:

The transition dialogues should look like this: For [ping]:

For [pingSimple]:

Within the outline view double click MrPing. Navigate the cursor to the behavior of MrPing. With the help of content assist create a new operation.

Name the operation [printData] and define the DemoData as a parameter.
Fill in the following code:
Operation printData(d: DemoData) : void {
"System.out.printf(\"d.int32Val: %d\\n\",d.int32Val);"
"System.out.printf(\"d.float64Val: %f\\n\",d.float64Val);"
"System.out.printf(\"d.int8Array: \");"
"for(int i = 0; i<d.int8Array.length; i++) {"
"System.out.printf(\"%d \",d.int8Array[i]);}"
"System.out.printf(\"\\nd.stringVal: %s\\n\",d.stringVal);"
}
For MrPing create the following state machine: (Remember that you can copy and paste the action code from the tutorial directory.)

The transition dialogues should look like this:
For [init]:

For [wait1]:

For [next]:

For [wait2]:

Open the Structure from SendingDataTop and add MrPing and MrPong as a reference. Connect the ports.

The model is finished now and can be found in /org.eclipse.etrice.tutorials/model/SendingData.
Generate the code by right click to [gen_SendingData.launch] and run it as [gen_SendingData]. Run the model. The output should look like this:
type ‚quit’ to exit /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 1 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 2 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 3 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 4 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 5 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 6 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 7 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 8 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 9 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPongSimple /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping data: 10 /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPong /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping /SendingData_SubSystem/SendigDataTopRef/ref1 -> looping d.int32Val: 4711 d.float64Val: 0,000000 d.int8Array: 1 2 3 4 5 6 7 8 9 10 d.stringVal: empty /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPong d.int32Val: 815 d.float64Val: 3,141234 d.int8Array: 100 101 102 103 104 105 106 107 108 109 d.stringVal: some contents /SendingData_SubSystem/SendigDataTopRef/ref0 -> waitForPong quit echo: quit
Within the first loop an integer value will be incremented by [MrPong] and sent back to [MrPing]. As long as the guard is true [MrPing] sends back the value.
Within the [next] transition, [MrPing] creates a data class and sends the default values. Then [MrPing] changes the values and sends the class again. At this point you should note that during the send operation, a copy of the data class will be created and sent. Otherwise it would not be possible to send the same object two times, even more it would not be possible to send a stack object at all. This type of data passing is called [sending data by value]. However, for performance reasons some applications requires [sending data by reference]. In this case the user is responsible for the life cycle of the object. In Java the VM takes care of the life cycle of an object. This is not the case for C/C++. Consider that a object which is created within a transition of a state machine will be destroyed when the transition is finished. The receiving FSM would receive an invalid reference. Therefore care must be taken when sending references.
For sending data by reference you simply have to add the keyword [ref] to the protocol definition.
Message ping(data: DemoData ref)
Make the test and inspect the console output.
The scope of this tutorial is to demonstrate how to receive model messages from outside the model. Calling methods which are not part of the model is simple and you have already done this within the blinky tutorial (this is the other way round: model => external code). Receiving events from outside the model is a very common problem and a very frequently asked question. Therefore this tutorial shows how an external event (outside the model) can be received by the model.
This tutorial is not like hello world or blinky. Being familiar with the basic tool features is mandatory for this tutorial. The goal is to understand the mechanism not to learn the tool features.
The idea behind the exercise is, to control a Pedestrian crossing light. We will use the same GUI as for the blinky tutorial but now we will use the [REQUEST] button to start a FSM, which controls the traffic lights.

The [REQUEST] must lead to a model message which starts the activity of the lights.
There are several possibilities to receive external events (e.g. TCP/UDP Socket, using OS messaging mechanism), but the easiest way is, to make a port usable from outside the model. To do that a few steps are necessary:
specify the messages (within a protocol) which should be sent into the model
model an actor with a port (which uses the specified protocol) and connect the port to the receiver
the external code should know the port (import of the port class)
the external code should provide a registration method, so that the actor is able to allow access to this port
the port can be used from the external code
Use the [New Model Wizzard] to create a new eTrice project and name it [PedLightsController].
Copy the package [org.eclipse.etrice.tutorials.PedLightGUI] to your [src] directory (see blinky tutorial).
In PedestrianLightWndNoTcp.jav uncomment line 15 (import), 36, 122 (usage) and 132-134 (registration). The error markers will disappear after the code is generated from the model.
Copy the model from /org.eclipse.etrice.tutorials/model/PedLightsController to your model file, or run the model directly in the tutorial directory.
Adapt the import statement to your path.
import room.basic.service.timing.* from "../../org.eclipse.etrice.modellib/models/TimingService.room"
Generate the code from the model.
Add the org.eclipse.etrice.modellib to the Java Class Path of your project.
All error markers should be disappeared and the model should be operable.
Arrange the Structure and the Statemachines to understand the model

The [GuiAdapter] represents the interface to the external code. It registers its [ControlPort] by the external code.

Visit the initial transition to understand the registration. The actor handles the incoming messages as usual and controls the traffic lights as known from blinky.

The [Controller] receives the [start] message and controls the timing of the lights. Note that the [start] message will be sent from the external code whenever the [REQUEST] button is pressed.
Visit the model and take a closer look to the following elements:
PedControlProtocol => notice that the start message is defined as usual
Initial transition of the [GuiAdapter] => see the registration
The [Controller] => notice that the [Controller] receives the external message (not the [GuiAdapter]). The [GuiAdapter] just provides its port and handles the incoming messages.
Visit the hand written code => see the import statement of the protocol class and the usage of the port.
Generate and test the model
Take a look at the generated MSC => notice that the start message will shown as if the [GuiAdapter] had sent it.

The tutorial shows that it is generally possible to use every port from outside the model as long as the port knows its peer. This is guaranteed by describing protocol and the complete structure (especially the bindings) within the model. The only remaining question is: Why is it safe and does not violate the „run to completion” semantic. To answer this question, take a look at the [MessageService.java] from the runtime environment. There you will find the receive method which puts each message into the queue.
@Override
public synchronized void receive(Message msg) {
if (msg!=null) {
messageQueue.push(msg);
notifyAll(); // wake up thread to compute message
}
}
This method is synchronized. That means, regardless who sends the message, the queue is secured. If we later on (e.g. for performance reasons in C/C++) distinguish between internal and external senders (same thread or not), care must be taken to use the external (secure) queue.
The actor is the basic building block for building systems with ROOM. An actor can be refined hierarchically and thus can be of arbitrarily large scope. Ports define the interface of an actor.
An ActorClass defines the type (or blueprint) of an actor. Hierarchies are built by ActorClasses that contain ActorReferences which have another ActorClass as type. The interface of an ActorClass is always defined by Ports.

The Behavior of an actor is usually defined by a state machine but could also be defined by manual code or other implementations.
Ports are the only interfaces of actors. A port has always a protocol assigned. Service Access Points (SAP) and Service Provision Points (SPP) are specialized ports that are used to define layering.
These symbols can only appear on the border of an actor class symbol.
![]() |
Class End Port |
![]() |
Conjugated Class End Port |
![]() |
Class Relay Port |
![]() |
Conjugated Class Relay Port |
![]() |
Replicated Class End Port |
![]() |
Conjugated Replicated Class End Port |
![]() |
Replicated Class Relay Port |
![]() |
Conjugated Replicated Class Relay Port |