2013-03-12 2 views
0

Я пытаюсь написать программу для загрузки файла в arduino. Программа может открывать последовательный порт и получать данные от arduino. Проблема возникает, когда я пытаюсь использовать обратный вызов функции в состоянии statechart, программа вылетает из строя.Использование boost :: bind для вызова функции в boost :: Statechart

Я раньше не использовал импульс и решил, что это будет хорошей возможностью попробовать.

У меня есть объект statechart с базовыми переходами: Idle; -> PortOpening; -> PortOpen; -> WaitForCurveChoiceConfirmation; -> ChooseFile; -> WaitForFileReceive; -> CompareFiles; -> CloseProgram;

Theres состояние закрытия порта тоже, но это прекрасно работает.

Моя главная программа только следующим образом

int main(int argc, char* argv[]){ 

    if(argc!=4){ 

    cerr<<"Usage: serialPort baudRate file"<<endl; 



    return 1; 

    } 

    try { 

    myInterface deviceInterface; 
    stateMachine fsm(deviceInterface); 
    fsm.initiate(); 

    } catch (std::exception& e) { 

    cerr<<"Exception: "<<e.what()<<endl; 

    } 

} 

Я могу открыть последовательный порт и получать данные отлично. Проблема возникает, когда я пытаюсь использовать обратный вызов функции в моем состоянии WaitForCurveChoiceConfirmation. Ардуино отправляет сообщение каждые несколько секунд, я использую вызов, когда программа получает полное сообщение. Как только сообщение будет получено, и будет вызван обратный вызов, моя программа выйдет из строя.

WaitForCurveChoiceConfirmationState выглядит следующим образом

class WaitForCurveChoiceConfirmation: public sc::state< WaitForCurveChoiceConfirmation, Active > { 

    public: 
     WaitForCurveChoiceConfirmation(my_context ctx); 
     typedef boost::mpl::list< 
      sc::custom_reaction<EvSensorChoiceConfirm> , 
      sc::custom_reaction<EvSensorChoiceTimeout> 
     > reactions; 

    sc::result react(const EvSensorChoiceConfirm &); 
    sc::result react(const EvSensorChoiceTimeout &); 
    void curveChoiceConfirmed(myMessage & msg); 
}; 

WaitForCurveChoiceConfirmation::WaitForCurveChoiceConfirmation(my_context ctx): my_base( ctx){ 
    context<stateMachine>().getInterface().setfullMsgReceivedCallback(boost::bind(&WaitForCurveChoiceConfirmation::curveChoiceConfirmed, this, _1)); 
} 

void WaitForCurveChoiceConfirmation::curveChoiceConfirmed(my1100Message & msg){ 
    std::cout << "curveChoiceConfirmed callback " << std::endl; 
    if(msg.isExpectingTemperatureCurve()){ 

     post_event(EvSensorChoiceConfirm()); 
    } 
} 

sc::result WaitForCurveChoiceConfirmation::react(const EvSensorChoiceConfirm &){ 
    std::cout<<"EvSensorChoiceConfirm"<<std::endl; 
    return transit<ChooseFile>(); 
} 

sc::result WaitForCurveChoiceConfirmation::react(const EvSensorChoiceTimeout &){ 
    return transit<PortClosing>(); 
} 

Соответствующие части класса MyInterface следующим

class myInterface: public CallbackAsyncSerial 
{ 

     /** Default constructor */ 
     myInterface(); 
     /** Default destructor */ 
     virtual ~myInterface(); 

     void processReceivedData(const char *data, unsigned int len); 
     void setfullMsgReceivedCallback(boost::function<void(myMessage &msg)>); 
     void clearfullMsgReceivedCallback(); 


    private: 

     boost::circular_buffer<char> * incomingMsg; 
     static const int MESSAGE_DATA_LENGTH = 73; //length of data, not including flags or checksum 
     static const uint8_t PROTOCOL_OUTGOING_LENGTH = 22; // number of characters in received message 
     uint8_t receive_buffer[MESSAGE_DATA_LENGTH + 2]; // plus 2 for checksum 
     char outgoingMsg[PROTOCOL_OUTGOING_LENGTH + 1]; 
     uint8_t statusByte; 
     uint8_t statusByte2; 
     uint8_t userByte; 
     uint8_t userByte2; 
     uint8_t notificationByte; 
     uint8_t errorByte; 
     uint8_t actionByte; 

     int msgIndex ; 
     int flagIndex ; 
     int byteCount; 
     int checkSum ; 
     int dispPreambleCount ; 
     int rcvCalculatedCheckSum ; 
     char rcvdFlag; 
     dispMsgState_t dispMsgState ; 

     static const int FLAG_COUNT = 17; 
     static const char flags[FLAG_COUNT] ; 
     boost::function<void(myMessage & msg)> fullMsgReceivedCallback; 


}; 

// this is used as a callback in CallBackAsyncSerial. It takes the data received by serial and processes it 
void myInterface::processReceivedData(const char *data, unsigned int len) 
{ 

    for (unsigned int i = 0; i < len; i++) 
    { 
     incomingMsg->push_back(data[i]); 
     switch (dispMsgState){ 
       case DISP_PREAMBLE: {//msg start flags 
        //std::cout << "DISP_PREAMBLE " <<std::endl; 
        if(incomingMsg->back() == START_FLAG){ 
         dispPreambleCount++; 
         if (dispPreambleCount == 5){ 
          dispMsgState = DISP_BYTE; 
          msgIndex = 0; 
          flagIndex = 0; 
          rcvCalculatedCheckSum = 5 * START_FLAG; 
          dispPreambleCount = 0; 
          rcvdFlag = 0; 
         } 
        } 
        else{ 
         dispPreambleCount = 0; //reset counter if a different character was found 

        } 
        incomingMsg->pop_back(); 
       } 
       break; 
       case DISP_BYTE:{ //status, user, notification, error bytes 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        receive_buffer[msgIndex] = incomingMsg->back(); 
        msgIndex++; 
        incomingMsg->pop_back(); 
        if (msgIndex == 7){ 
         dispMsgState = DISP_INTEGER_FLAG; 
        } 
       } 
       break; 
       case DISP_INTEGER_FLAG:{ //integer flag 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        rcvdFlag = incomingMsg->back(); 
        incomingMsg->pop_back(); 
        dispMsgState = DISP_INTEGER; 
       } 
       break; 
       case DISP_INTEGER:{ // integers 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        if(rcvdFlag == flags[flagIndex]){ 
         receive_buffer[msgIndex] = incomingMsg->back(); 
        } 
        incomingMsg->pop_back(); 
        msgIndex++; 


        byteCount++; 
        if (byteCount >= 2){ 
         if(msgIndex < 21){ 
          dispMsgState = DISP_INTEGER_FLAG; 
         } 
         else{ 
          dispMsgState = DISP_FLOAT_FLAG; 
         } 
         byteCount = 0; 
         flagIndex++; 
        } 
       } 
       break; 
       case DISP_FLOAT_FLAG:{ // float flag 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        rcvdFlag = incomingMsg->back(); 
        incomingMsg->pop_back(); 
        dispMsgState = DISP_FLOAT; 
       } 
       break; 
       case DISP_FLOAT:{ // floats 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        if(rcvdFlag == flags[flagIndex]){ 
         receive_buffer[msgIndex] = incomingMsg->back(); 
        } 
        incomingMsg->pop_back(); 

        msgIndex++; 

        byteCount++; 
        if (byteCount >= 4){ 
         if(msgIndex < 49){ 
          dispMsgState = DISP_FLOAT_FLAG; 
         } 
         else{ 
          dispMsgState = DISP_STRING_FLAG; 
         } 
         byteCount = 0; 
         flagIndex++; 
        } 
       } 
       break; 
       case DISP_STRING_FLAG:{ // pressure flag 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        rcvdFlag = incomingMsg->back(); 
        incomingMsg->pop_back(); 
        dispMsgState = DISP_STRING; 
       } 
       break; 
       case DISP_STRING:{ // pressure string 
        rcvCalculatedCheckSum += incomingMsg->back(); 
        if(rcvdFlag == flags[flagIndex]){ 
         receive_buffer[msgIndex] = incomingMsg->back(); 
        } 
        incomingMsg->pop_back(); 
        msgIndex++; 

        byteCount++; 
        if (byteCount >= 8){ 
         if(msgIndex < 73){ 
          dispMsgState = DISP_STRING_FLAG; 
         } 
         else{ 
          dispMsgState = DISP_CHECKSUM; 
         } 
         byteCount = 0; 
         flagIndex++; 
        } 
       } 
       break; 
       case DISP_CHECKSUM:{ // rcv checksum 
        if (byteCount == 0){ 
         receive_buffer[msgIndex ] = incomingMsg->back() ; 
         byteCount ++; 

        } 
        else{ 

         receive_buffer[msgIndex ] = incomingMsg->back(); 

         if (rcvCalculatedCheckSum == ((receive_buffer[msgIndex - 1 ] << 8) | receive_buffer[msgIndex ])) { 


          std::cout<<"FULL MSG CONFIRMED "<<std::endl; 
          statusByte = receive_buffer[0]; 
          statusByte2 = receive_buffer[1]; 
          userByte = receive_buffer[2]; 
          userByte2 = receive_buffer[3]; 
          notificationByte = receive_buffer[4]; 
          errorByte = receive_buffer[5]; 
          actionByte = receive_buffer[6]; 

          myMessage * msg = new myMessage(); 
          msg->initialise(statusByte,statusByte2,userByte,userByte2,notificationByte,errorByte,actionByte) ; 
          std::cout<<"made new msg"<<std::endl; 
          fullMsgReceivedCallback(*msg); //THIS IS WHERE IT CRASHES 
          std::cout<<"callback returned"<<std::endl; 
          delete msg; 
          std::cout<<"msg deleted"<<std::endl; 

          /* to convert string to float 
          #include <sstream> 
          using namespace std; 
          string s = "1.60000000000000000000000000000000000e+01"; 
          istringstream os(s); 
           double d; 
          os >> d; 
          cout << d << endl; 
          */ 


         } 
         else{ 
          std::cout<<"FULL MSG NOT CONFIRMED "<<std::endl; 
          std::cout << std::hex << rcvCalculatedCheckSum <<" " << std::hex<< int((receive_buffer[msgIndex - 1 ]))<<" "<< std::hex << int(receive_buffer[msgIndex ])<<std::endl; 


         } 




         dispMsgState = DISP_PREAMBLE; 
         rcvCalculatedCheckSum = 0; 
         msgIndex = 0; 
         byteCount = 0; 

        } 
        msgIndex++; 
        incomingMsg->pop_back(); 


       } 
       break; 


     } 

    } 
    //incomingMsg->insert(incomingMsg->end(), data, data + len); 
    //for(boost::circular_buffer<char>::const_iterator i = incomingMsg->begin(); i != incomingMsg->end(); ++i) 
    // std::cout << *i ; 

    for(int i = 0; i < MESSAGE_DATA_LENGTH + 1; i++){ 
     //std::cout << std::hex<< (uint8_t)*i << ' ' ; 

     std::cout << std::hex << receive_buffer[i] << ' '; 

    } 
    std::cout <<endl; 

} 

void myInterface::setfullMsgReceivedCallback(boost::function<void(my0Message & msg)> cb){ 
    fullMsgReceivedCallback = cb; 
} 


void myInterface::clearfullMsgReceivedCallback(){ 
    fullMsgReceivedCallback = NULL; 
} 

Катастрофа происходит в строке "fullMsgReceivedCallback (* Msg);" in processReceivedData. Я уверен, что я просто привязываю функцию неправильно или объявляю объект указателя функции некорректно.

Может ли кто-нибудь увидеть, где я ошибаюсь?

спасибо за вашу помощь

ответ

0

мне удалось решить. Это не было ничего общего с statechart, bind или функцией.

Это была моя ошибка при вызове обратного вызова. Я вызывал обратный вызов «full message received», даже если у него не было обратного вызова, назначенного ему, и было просто NULL. Я установил это, добавив, и если пункт:

if (fullMsgReceivedCallback!= NULL){ 
    Message * msg = Message ; 
    std::cout<<"made new msg"<<std::endl; 
    msg->initialise(statusByte,statusByte2,userByte,userByte2,notificationByte,errorByte,actionByte); 
    std::cout<<" msg initialised"<<std::endl; 
    fullMsgReceivedCallback(*msg); 
    delete msg; 
    std::cout<<"msg deleted"<<std::endl; 
} 
+0

Возможно, у вас есть помощь, если вы уменьшили проблему до, скажем, 10 строк кода. Это больше для вас, но меньше для всех остальных. Я также обнаружил, что иногда сам процесс сокращения сам отвечает на проблему. Просто мысль. – Ant

Смежные вопросы