| 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() |
| } |
| } |
| } |