Dependency Injection: Stopper Workflows
Table of Contents
Introduction
We have already defined the interfaces for a status and for a workflow status. We can use these to build state machines later. Now we build the individual states for the two workflows, send and receive.
Abstract Workflow State
Abstract Class AbstractWorkflowState FUNCTION_BLOCK ABSTRACT AbstractWorkflowState IMPLEMENTS IWorkfowState
VAR
nextState :IStatemachine;
END_VAR
|
METHOD ABSTRACT executeState :IStatemachine
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
END_VAR
|
THIS^.nextState := nextState;
|
METHOD setNextState
VAR_INPUT
nextState : IStatemachine;
END_VAR
|
THIS^.nextState := nextState;
|
Receiving Workflow
Class StateReceivingWorkflow FUNCTION_BLOCK StateReceivingWorkflow EXTENDS AbstractWorkflowState
VAR
cylinder :ICylinder;
jamSensor :IDigitalSensor;
transportInterface :ITransportInterfaceForReceiver;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
cylinder :ICylinder;
jamSensor :IDigitalSensor;
transportInterface :ITransportInterfaceForReceiver;
END_VAR
|
THIS^.cylinder := cylinder;
THIS^.jamSensor := jamSensor;
THIS^.transportInterface := transportInterface;
|
METHOD executeState :IStatemachine
VAR
read2Receive :BOOL;
partReceived :BOOL;
END_VAR
|
read2Receive := (THIS^.cylinder.isAtHomePosition);
partReceived := (THIS^.jamSensor.isOccupied);
executeState := THIS^;
IF (read2Receive AND (NOT partReceived)) THEN
THIS^.transportInterface.resetPartIsArrived();
THIS^.transportInterface.setIAmReadyToReceive();
ELSIF (partReceived) THEN
THIS^.transportInterface.resetIAmReadyToReceive();
THIS^.transportInterface.setPartIsArrived();
executeState := THIS^.nextState;
ELSE
THIS^.transportInterface.resetIAmReadyToReceive();
END_IF
|
Sending Workflow
Class StateReleaseCarrier FUNCTION_BLOCK StateReleaseCarrier EXTENDS AbstractWorkflowState
VAR
conveyorInterface :IConveyorInterface;
stopperCylinder :ICylinder;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
conveyorInterface :IConveyorInterface;
stopperCylinder :ICylinder;
END_VAR
|
THIS^.conveyorInterface := conveyorInterface;
THIS^.stopperCylinder := stopperCylinder;
|
METHOD executeState :IStatemachine
|
THIS^.conveyorInterface.setStartRequest();
THIS^.stopperCylinder.moveToWorkPosition();
IF (THIS^.conveyorInterface.conveyorIsRunning AND THIS^.stopperCylinder.isAtWorkPosition) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateStartConveyor FUNCTION_BLOCK StateStartConveyor EXTENDS AbstractWorkflowState
VAR
conveyorInterface :IConveyorInterface;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
conveyorInterface :IConveyorInterface;
END_VAR
|
THIS^.conveyorInterface := conveyorInterface;
|
METHOD executeState :IStatemachine
|
THIS^.conveyorInterface.setStartRequest();
IF (THIS^.conveyorInterface.conveyorIsRunning) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateStopNextCarrier FUNCTION_BLOCK StateStopNextCarrier EXTENDS AbstractWorkflowState
VAR
conveyorInterface :IConveyorInterface;
stopperCylinder :ICylinder;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
conveyorInterface :IConveyorInterface;
stopperCylinder :ICylinder;
END_VAR
|
THIS^.conveyorInterface := conveyorInterface;
THIS^.stopperCylinder := stopperCylinder;
|
METHOD executeState :IStatemachine
|
THIS^.conveyorInterface.setStartRequest();
THIS^.stopperCylinder.moveToHomePosition();
IF (THIS^.stopperCylinder.isAtHomePosition) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateWaitForCarrierToSend FUNCTION_BLOCK StateWaitForCarrierToSend EXTENDS AbstractWorkflowState
VAR
stopperSensor :IDigitalSensor;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
stopperSensor :IDigitalSensor;
END_VAR
|
THIS^.stopperSensor := stopperSensor;
|
METHOD executeState :IStatemachine
|
IF (THIS^.stopperSensor.isOccupied) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateWaitUntilCarrierIsArrived FUNCTION_BLOCK StateWaitUntilCarrierIsArrived EXTENDS AbstractWorkflowState
VAR
receiverInterface :ITransportInterfaceForSender;
conveyorInterface :IConveyorInterface;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
receiverInterface :ITransportInterfaceForSender;
conveyorInterface :IConveyorInterface;
END_VAR
|
THIS^.receiverInterface := receiverInterface;
THIS^.conveyorInterface := conveyorInterface;
|
METHOD executeState :IStatemachine
|
THIS^.conveyorInterface.setStartRequest();
IF ((
THIS^.receiverInterface.partIsArrivedAtNext
) OR (
NOT THIS^.receiverInterface.nextIsReadyToRecive
)
) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateWaitUntilCarrierIsGone FUNCTION_BLOCK StateWaitUntilCarrierIsGone EXTENDS AbstractWorkflowState
VAR
stopperSensor :IDigitalSensor;
conveyorInterface :IConveyorInterface;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
stopperSensor :IDigitalSensor;
conveyorInterface :IConveyorInterface;
END_VAR
|
THIS^.stopperSensor := stopperSensor;
THIS^.conveyorInterface := conveyorInterface;
|
METHOD executeState :IStatemachine
|
THIS^.conveyorInterface.setStartRequest();
IF (THIS^.stopperSensor.isFree) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|
Class StateWaitUntilReceiverIsReady FUNCTION_BLOCK StateWaitUntilReceiverIsReady EXTENDS AbstractWorkflowState
VAR
receiverInterface :ITransportInterfaceForSender;
END_VAR
|
METHOD FB_init :BOOL
VAR_INPUT
// if TRUE, the retain variables are initialized (warm start / cold start)
bInitRetains :BOOL := FALSE;
// if TRUE, the instance afterwards gets moved into the copy code (online change)
bInCopyCode :BOOL := TRUE;
nextState :IStatemachine;
receiverInterface :ITransportInterfaceForSender;
END_VAR
|
THIS^.receiverInterface := receiverInterface;
|
METHOD executeState :IStatemachine
|
IF (THIS^.receiverInterface.nextIsReadyToRecive) THEN
executeState := THIS^.nextState;
ELSE
executeState := THIS^;
END_IF
|