blob: 8423233b9a9418d402aaa7898dd15dce75c5dac2 [file] [log] [blame]
RoomModel TrafficLight {
import etrice.api.types.boolean
import etrice.api.types.char
import etrice.api.types.int32
import etrice.api.timer.PTimer
import etrice.api.tcp.PTcpPayload
import etrice.api.tcp.PTcpControl
import etrice.api.tcp.ATcpClient
ActorClass TestApplication ["The TestApplication contains the PedestrianTrafficLightController and its test harness."] {
Structure {
ActorRef controller: PedestrianTrafficLightController
ActorRef controllerTestHarness: TrafficLightControllerTestHarness
Binding controllerTestHarness.fct and controller.fct
Binding controller.tlInterface and controllerTestHarness.tlInterface
}
Behavior {
}
}
ActorClass SingleTrafficLight ["OneTrafficLight contains the PedestrianTrafficLightController which is connected via a SocketClient Actor to the traffic light GUI."] {
Structure {
ActorRef controller: PedestrianTrafficLightController
ActorRef headquarters1: TrafficLightHeadquarters
ActorRef tcpClient: ATcpClient
ActorRef ref0: TrafficLightInterface
Binding headquarters1.controllers and controller.fct
Binding ref0.ctrl and tcpClient.controlPort
Binding ref0.payload and tcpClient.payloadPort
Binding ref0.fct and controller.tlInterface
}
Behavior {
}
}
ActorClass FlatReplication ["FlatReplication uses several replicated Actors in a row to control 2 traffic lights."] {
Structure {
ActorRef controller [2]: PedestrianTrafficLightController
ActorRef headquarters1: TrafficLightHeadquarters
ActorRef tlInterface [2]: TrafficLightInterface
ActorRef tcpClient [2]: ATcpClient
Binding headquarters1.controllers and controller.fct
Binding controller.tlInterface and tlInterface.fct
Binding tlInterface.ctrl and tcpClient.controlPort
Binding tlInterface.payload and tcpClient.payloadPort
}
Behavior {
}
}
ActorClass HierarchicalReplication ["HierarchicalReplication structural hierarchy to combine several actors and replicate them 'en bloc'. It controls 2 traffic lights."] {
Structure {
ActorRef controllerWithInfrastructure [2]: TrafficLightControllerWithInfrastructure ["This is replicated "]
ActorRef headquarters2: TrafficLightHeadquarters
Binding controllerWithInfrastructure.fct and headquarters2.controllers
}
Behavior {
}
}
ActorClass TrafficLightControllerWithInfrastructure ["The TrafficLightControllerWithInfrastructure encapsulates the PedestrianTrafficLightController, the TrafficLightInterface and the SocketClient."] {
Interface {
Port fct: PTrafficLightController
}
Structure {
ActorRef controller: PedestrianTrafficLightController
ActorRef tlInterface: TrafficLightInterface
ActorRef tcpClient: ATcpClient
Binding controller.tlInterface and tlInterface.fct
Binding fct and controller.fct
Binding tlInterface.ctrl and tcpClient.controlPort
Binding tlInterface.payload and tcpClient.payloadPort
}
Behavior {
}
}
ActorClass TrafficLightControllerTestHarness [
"Test harness for the TrafficLightController. It has the same ports, but conjugated. It can run test cases for the TrafficLightController by completely simulating its environment."
] {
Interface {
conjugated Port fct: PTrafficLightController
Port tlInterface: PTrafficLightInterface
}
Structure {
external Port fct
external Port tlInterface
SAP to: PTimer
Attribute counter: int32 ["FEATURE: Attribute of an ActorClass"]
}
Behavior {
StateMachine {
Transition init: initial -> SetStandby
Transition tr0: SetStandby -> InStandby {
triggers {
<connect: tlInterface>
}
action '''
counter=0;
tlInterface.connected();'''
}
Transition tr1: InStandby -> SetStart {
triggers {
<setCarYellow: tlInterface guard '''++counter==5'''>
}
}
Transition tr2: SetStart -> InRunning {
triggers {
<doneStart: fct>
}
}
Transition tr3: InRunning -> CarGreen {
triggers {
<setCarGreen: tlInterface guard '''transitionData==1'''>
}
}
Transition tr4: CarGreen -> PressButton {
triggers {
<timeout: to>
}
}
Transition tr5: PressButton -> CarGreenAgain {
triggers {
<setCarGreen: tlInterface guard '''transitionData==1'''>
}
}
Transition tr6: CarGreenAgain -> CarYellow {
triggers {
<setCarYellow: tlInterface guard '''transitionData==1'''>
}
action '''counter=0;'''
}
Transition tr7: CarYellow -> SetStop {
triggers {
<setPedRed: tlInterface guard '''++counter==5'''>
}
}
Transition tr8: SetStop -> Done {
triggers {
<doneStop: fct>
}
}
State SetStandby {
entry '''fct.standby(0); // dummy port not used'''
}
State InStandby {
entry '''printf("InStandby\n");'''
}
State SetStart {
entry '''
fct.start();
printf("SetStart\n");'''
}
State InRunning {
entry '''printf("InRunning\n");'''
}
State CarGreen {
entry '''
to.startTimeout(1*10);
printf("CarGreen\n");'''
}
State PressButton {
entry '''
tlInterface.pressedRequestButton();
printf("PressButton\n");'''
}
State CarGreenAgain {
entry '''
fct.standby(0); // dummy port
printf("CarGreenAgain\n");'''
}
State CarYellow {
entry '''printf("CarYellow\n");'''
}
State SetStop {
entry '''
fct.stop();
printf("SetStop\n");'''
}
State Done {
entry '''printf("Done\n");'''
}
}
}
}
ActorClass PedestrianTrafficLightController [
"Control of a traffic light at a pedestrian crossing with one car traffic light and one pedestrian traffic light." ] {
Interface {
Port fct: PTrafficLightController
conjugated Port tlInterface: PTrafficLightInterface
}
Structure {
external Port fct
external Port tlInterface
SAP to: PTimer
Attribute timeBase: int32
}
Behavior {
StateMachine {
Transition init: initial -> Stopped {
action '''timeBase = 100;'''
}
Transition tr0: Stopped -> Connecting {
triggers {
<standby: fct>
}
action '''
printf("ptlc: connecting to port %d\n", (int)transitionData);
tlInterface.connect(transitionData);
'''
}
Transition tr1: Standby -> tpStart of Running {
triggers {
<start: fct>
}
}
Transition tr2: Running -> AllRedBeforeStandby {
triggers {
<standby: fct>
}
}
Transition tr3: tpStandby of Running -> AllRedBeforeStandby
Transition tr4: AllRedBeforeStandby -> tp0 of Standby {
triggers {
<timeout: to>
}
}
Transition tr5: Standby -> Stopped {
triggers {
<stop: fct>
}
}
Transition tr6: Connecting -> tp0 of Standby {
triggers {
<connected: tlInterface>
}
}
State Stopped {
entry '''
tlInterface.setCarRed(0);
tlInterface.setCarYellow(0);
tlInterface.setCarGreen(0);
tlInterface.setPedRed(0);
tlInterface.setPedGreen(0);
fct.doneStop();'''
}
State Standby {
entry '''fct.doneStandby();'''
subgraph {
Transition tr0: my tp0 -> On
Transition tr1: On -> Off {
triggers {
<timeout: to>
}
}
Transition tr2: Off -> On {
triggers {
<timeout: to>
}
}
EntryPoint tp0
State On {
entry '''
// turn two lights on
tlInterface.setCarYellow(1);
tlInterface.setPedRed(1);
// start timeout (fire once) for blinking
// startTimer would start a cyclic timer
to.startTimeout(5*timeBase);'''
exit '''
// TIP: turn off lights here in the exit code of state On instead of the entry code of state Off
// to make sure they are turned off if the superstate Standby is left by a group transition
tlInterface.setCarYellow(0);
tlInterface.setPedRed(0);
// TIP: kill timer here to make sure it is killed if the state is left by a group transition or any other transition than a timeout
// ALTERNATIVE: kill() could also be placed in the exit code of the superstate StandbyBlinking and so replacing the two calls in On:exit and Off:exit
to.kill();'''
}
State Off {
entry '''to.startTimeout(5*timeBase);'''
exit '''to.kill();'''
}
}
}
State Running {
entry '''fct.doneStart();'''
exit '''to.kill();'''
subgraph {
Transition tr0: my tpStart -> AllRed
Transition tr1: AllRed -> CarRedYellow {
triggers {
<timeout: to>
}
}
Transition tr2: CarGreen -> CarYellow {
triggers {
<pressedRequestButton: tlInterface>
}
}
Transition tr3: CarYellow -> CarRed {
triggers {
<timeout: to>
}
}
Transition tr4: CarRed -> PedGreen {
triggers {
<timeout: to>
}
}
Transition tr5: PedGreen -> AllRed {
triggers {
<timeout: to>
}
}
Transition tr6: CarGreen -> CarYellowBeforeStandby {
triggers {
<standby: fct>
}
}
Transition tr7: CarYellowBeforeStandby -> my tpStandby {
triggers {
<timeout: to>
}
}
Transition tr8: CarRedYellow -> CarGreen {
triggers {
<timeout: to>
}
}
EntryPoint tpStart
ExitPoint tpStandby
State AllRed {
entry '''
tlInterface.setCarRed(1);
tlInterface.setPedRed(1);
tlInterface.setPedGreen(0);
to.startTimeout(10*timeBase);'''
}
State CarYellow {
entry '''
tlInterface.setCarGreen(0);
tlInterface.setCarYellow(1);
to.startTimeout(10*timeBase);'''
}
State CarGreen {
entry '''
tlInterface.setCarRed(0);
tlInterface.setCarYellow(0);
tlInterface.setCarGreen(1);'''
}
State CarRed {
entry '''
tlInterface.setCarYellow(0);
tlInterface.setCarRed(1);
to.startTimeout(10*timeBase);'''
}
State PedGreen {
entry '''
tlInterface.setPedRed(0);
tlInterface.setPedGreen(1);
to.startTimeout(20*timeBase);'''
}
State CarYellowBeforeStandby {
entry '''
tlInterface.setCarGreen(0);
tlInterface.setCarYellow(1);
to.startTimeout(10*timeBase);'''
}
State CarRedYellow {
entry '''
tlInterface.setCarYellow(1);
to.startTimeout(10*timeBase);'''
}
}
}
State AllRedBeforeStandby {
entry '''
tlInterface.setCarRed(1);
tlInterface.setPedRed(1);
to.startTimeout(30*timeBase);'''
}
State Connecting
}
}
}
ActorClass TrafficLightInterface {
Interface {
Port fct: PTrafficLightInterface
conjugated Port ctrl: PTcpControl
conjugated Port payload: PTcpPayload
}
Structure {
external Port fct
external Port ctrl
external Port payload
}
Behavior {
Operation sendPayloadString(data: char ref) '''
DTcpPayload package;
DTcpPayload_setAsString(&package, data);
payload.dataPackage(&package);'''
Operation sendOnOffCommand(lightString: char ref, status: boolean) '''
DTcpPayload package;
strcpy(package.data, lightString);
if (status==0){
strcat(package.data, "=off\n");
}
else {
strcat(package.data, "=on\n");
}
printf("package=%s", package.data);
package.length = strlen(package.data);
payload_dataPackage(&package);'''
StateMachine {
Transition init: initial -> Disconnected
Transition tr0: Connected -> Connected {
triggers {
<setCarRed: fct>
}
action '''sendOnOffCommand("setCarLightRed", transitionData);'''
}
Transition tr1: Connecting -> Connected {
triggers {
<connected: ctrl>
}
action '''fct.connected();'''
}
Transition tr2: Disconnected -> Connecting {
triggers {
<connect: fct>
}
action '''
printf("tli: connecting to port %d\n", (int)transitionData);
DTcpControl config = {"localhost", transitionData};
ctrl.connect(&config);'''
}
Transition tr3: Connected -> Connected {
triggers {
<setCarYellow: fct>
}
action '''sendOnOffCommand("setCarLightYellow", transitionData);'''
}
Transition tr4: Connected -> Connected {
triggers {
<setCarGreen: fct>
}
action '''sendOnOffCommand("setCarLightGreen", transitionData);'''
}
Transition tr5: Connected -> Connected {
triggers {
<setPedRed: fct>
}
action '''sendOnOffCommand("setPedLightRed", transitionData);'''
}
Transition tr6: Connected -> Connected {
triggers {
<setPedGreen: fct>
}
action '''sendOnOffCommand("setPedLightGreen", transitionData);'''
}
Transition tr7: Connected -> Connected {
triggers {
<dataPackage: payload>
}
action '''
char *pressedRequestButtonString = {"pressedRequestButton\n"};
int32 len = strlen(pressedRequestButtonString);
if ( (transitionData->length == len) && memcmp(transitionData->data, "pressedRequestButton", len)){
fct.pressedRequestButton();
}'''
}
Transition tr8: Connected -> Connected {
triggers {
<setRequestButtonActive: fct>
}
action '''sendOnOffCommand("setRequestButtonActive", transitionData);'''
}
State Connecting
State Connected
State Disconnected
}
}
}
ActorClass TrafficLightInterfaceStub {
Interface {
Port fct: PTrafficLightInterface
}
Structure {
external Port fct
SAP to: PTimer
}
Behavior {
StateMachine {
Transition init: initial -> WaitingABit
Transition tr0: WaitingABit -> PressButton {
triggers {
<timeout: to>
}
}
State WaitingABit {
entry '''to.startTimeout(80*10);'''
}
State PressButton {
entry '''
fct.pressedRequestButton();
'''
}
}
}
}
ActorClass TrafficLightHeadquarters {
Interface {
conjugated Port controllers [2]: PTrafficLightController
}
Structure {
external Port controllers
SAP to: PTimer
}
Behavior {
StateMachine {
Transition init: initial -> Standby
Transition tr0: Standby -> Running {
triggers {
<timeout: to>
}
}
Transition tr1: Running -> Stopped {
triggers {
<timeout: to>
}
}
State Standby {
entry '''
int n = PTrafficLightControllerReplPort_getReplication(&self->constData->controllers);
int i;
printf("hq: number of connections is %d\n", n);
for (i=0; i<n; ++i)
controllers[i].standby(4441+i);
to.startTimeout(200*10);'''
}
State Running {
entry '''
controllers.start();
to.startTimeout(200*10);'''
}
State Stopped {
entry '''controllers.stop();'''
}
}
}
}
ProtocolClass PTrafficLightController {
incoming {
Message standby(int32)
Message start()
Message stop()
}
outgoing {
Message doneStandby()
Message doneStart()
Message doneStop()
}
}
ProtocolClass PTrafficLightInterface {
incoming {
Message connect(int32)
Message setCarRed(boolean)
Message setCarYellow(boolean)
Message setCarGreen(boolean)
Message setPedRed(boolean)
Message setPedGreen(boolean)
Message setRequestButtonActive(boolean)
}
outgoing {
Message connected()
Message pressedRequestButton()
}
}
}