EventHelix.com: CASE Tools; Real-time and Embedded System Design; Object Oriented Design
  Home  |  EventStudio System Designer 5  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us  Blog

Input Belt State Machine Design

We have already defined the sequence diagrams for the Helix Router. This article will focus on designing the C++ classes to implement the design defined by the sequence diagrams. We will step through the development process of one of the most complicated classes in the system, the InputConveyorBelt.

The design process is divided into three distinct steps:

State Machine

Here is the state machine design derived from the Helix Router Sequence Diagrams we developed earlier:

state transition diagram for Input Belt

Refining the State Machine

Based on the above design we have defined a state hierarchy. The states have been classified into Inservice and OutOfService base states.

state hierarchy for input belt

Implementation

The source code for the Input Conveyor Belt is based almost completely the sequence diagrams. The Input Conveyor Belt has been modeled as a hierarchical state machine

Input Conveyor Belt Header File
class InputConveyorBelt : public ConveyorBelt
 {
    . . .
 
    MagneticSensor *m_pMagneticSensor;
    Package *m_pCurrentPackage;
       
    // State description   
    class BaseState
    {
    public:
       // Dummy handlers 
       void HandleSensorInterrupt(InputConveyorBelt& m)  {}
       void HandleAcknowledgePackage(InputConveyorBelt &m, 
                                     const AcknowledgePackageMsg *pMsg) {}
       void HandleSensorTimeout(InputConveyorBelt &m) {}
       void OperatorInservice(InputConveyorBelt &m) {}
       
       void ConfigureBelt(InputConveyorBelt &m, const ConfigMsg *pMsg) {}
       
       // Handlers implementing functionality
       void UnConfigureBelt(InputConveyorBelt &m, const UnConfigMsg *pMsg);
    };
    
    class Inservice : public InputBeltBaseState
    {
       . . .
    };
    
    class OutOfService : public InputBeltBaseState
    {
      . . .
    };
    
    class Idle : public Inservice
    {
    public:
        void HandleSensorInterrupt(InputConveyorBelt& m);   
    };
    
    class AwaitingPackageRouting : public Inservice
    {
    public:
       void HandleAcknowledgePackage(InputConveyorBelt &m, 
                                     const AcknowledgePackageMsg *pMsg);
       void HandleSensorTimeout(InputConveyorBelt &m);
   
       // Unconfigure is not supported in this state, so add a dummy handler to
       // override handling of this event by the base state
       void UnConfigureBelt(InputConveyorBelt &m, const UnConfigMsg *pMsg) {}
    };
    
    class Jammed : public OutOfService
    {
    public: 
       void OperatorInservice(InputConveyorBelt &m);       
    };
    
    class AwaitingConfiguration : public OutOfService
    {
    public:
       void ConfigureBelt(InputConveyorBelt &m, const ConfigMsg *pMsg);
    };
 
    // Friend declarations
    friend BaseState;
    friend Inservice;
    friend OutOfService;
    friend Idle;
    friend AwaitingPackageRouting;
    friend Jammed;
    friend AwaitingConfiguration; 
    
    // Static declaration for states
    static Idle idle;
    static AwaitingPackageRouting awaitingPackageRouting;
    static Jammed jammed;
    static AwaitingConfiguration awaitingConfiguration; 
    
    // Current state pointer
    BaseState *m_pCurrentState;
    
    // Method to change state
    void ChangeState(BaseState &state)
    {  m_pCurrentState = &state; }
    
 public:
 
    InputConveyorBelt(int beltId) : ConveyorBelt(beltId) 
    {
       ChangeState(awaitingConfiguration);
    }
    
    // Public handlers (implemented as inline functions)
    void HandleSensorInterrupt()
    {   m_pCurrentState->HandleSensorInterrupt(*this); }
    
    void HandleAcknowledgePackage(const AcknowledgePackageMsg *pMsg)
    {   m_pCurrentState->HandleAcknowledgePackage(*this, 
                                  const AcknowledgePackageMsg *pMsg); }
                                                                  
    void HandleSensorTimeout()
    {   m_pCurrentState->HandleSensorTimeout(*this); }
    
    void OperatorInservice()
    {   m_pCurrentState->OperatorInservice(*this); }

    void ConfigureBelt(const ConfigMsg *pMsg)
    {   m_pCurrentState->ConfigureBelt(*this, pMsg); }
        
    void UnConfigureBelt(const UnConfigMsg *pMsg)
    {   m_pCurrentState->UnConfigureBelt(*this, const UnConfigMsg *pMsg); }
    
 };

 

Input Conveyor Belt Source File
 // Static state variables
InputConveyorBelt::Idle InputConveyorBelt::idle;
InputConveyorBelt::AwaitingPackageRouting InputConveyorBelt::awaitingPackageRouting;
InputConveyorBelt::Jammed InputConveyorBelt::jammed;
InputConveyorBelt::AwaitingConfiguration InputConveyorBelt::awaitingConfiguration; 

// Base state implementation for UnConfigure executes in all state unless 
// explicitly overriden by a state
void InputConveyorBelt::BaseState::HandleUnConfigure(InputConveyorBelt &m, 
                                                     UnConfigMsg *pMsg)
{
   // Conveyor Belt has been unconfigured, so deactivate the sensor
   m_pMagneticSensor->Deactivate();
   
   // Delete the sensor as it is no longer required.
   delete m_pMagneticSensor;
   
   // Move to unconfigured state
   m.ChangeState(m.awaitingConfiguration);   
}

void InputConveyorBelt::Idle::HandleSensorInterrupt(InputCoveyorBelt &m)
{
    // Create a package object to keep track of the package
    m_pCurrentPackage = new Package(m_beltId);
    
    // Now read the sensor to get information about the sensor
    SensorInfo *pSensorInfo = m_pMagneticSensor->ReadSensor();
    
    // Save the product info in the package
    m_pCurrentPackage->SetProductInfo(pSensorInfo->productInfo);
    
    // Obtain the destination conveyor belt id from the 
    // routing table
    int destinationBeltId =  
              RoutingTable::GetInstance()->GetRouting(m_pCurrentPackage);
    
    // Store the desitnation belt id in the package
    pPackage->SetDestinationBeltId(destinationBeltId);
    
    // Set the router to pass the package to the destination belt
    // Note: This important step was missed during sequence diagram design
    Router::GetInstance()->SetRouterTo(destinationBeltId);
    
    // Start a timer to check for timely routing of the package
    StartTimer(T_AWAIT_PACKAGE_ROUTING);
    
    // Change state to awaiting package
    m.ChangeState(m.awaitingPackageRouting);
}

void InputConveyorBelt::AwaitingPackageRouting::HandleAcknowledgePackage
                  (InputConveyorBelt &m, const AcknowledgePackageMsg *pMsg)
{
    // Package has been acknowledged by the destination conveyor belt
    // so stop the timer
    StopTimer(T_AWAIT_PACKAGE_ROUTING);

    // Delete the package object as routing has been completed
    delete m_pCurrentPackage;
    
    // Now move back to idle state
    m.ChangeState(m.idle);
}
                      
void InputConveyorBelt::AwaitingPackageRouting::HandleSensorTimeout
                  (InputConveyorBelt &m)
{
    // Package is jammed so we can delete the package
    // object keeping track of the package related information
    delete m_pCurrentPackage;
    
    // Raise the jammed alarm
    Router::GetInstance()->RaiseAlarm(m_beltId, JAMMED_ALARM);
    
    // Now move back to idle state
    m.ChangeState(m.jammed);
}

void InputConveyorBelt::Jammed::OperatorInservice(InputConveyorBelt &m)
{
    
    // Clear the jammed alarm
    Router::GetInstance()->ClearAlarm(m_beltId, JAMMED_ALARM);

   // Operator has fixed the jam condition and is requesting a transition to
   // inservice state
   m.ChangeState(m.idle);
}

void InputConveyorBelt::AwaitingConfiguration::ConfigureBelt
                   (InputConveyorBelt &m, const ConfigMsg *pMsg)
{
   // Create the magnetic sensor
   m_pMagneticSensor = new MagneticSensor;
   
   // Activate the sensor
   m_pMagneticSensor->Activate();
   
   // Move to the idle state
   m.ChangeState(m.idle);
}     

 

  Home  |  EventStudio System Designer 5  |  VisualEther Protocol Analyzer 1.0  Real-time Mantra  Contact Us Blog
Copyright © 2000-2011 EventHelix.com Inc. All Rights Reserved.