Я пытаюсь написать программу для загрузки файла в 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. Я уверен, что я просто привязываю функцию неправильно или объявляю объект указателя функции некорректно.
Может ли кто-нибудь увидеть, где я ошибаюсь?
спасибо за вашу помощь
Возможно, у вас есть помощь, если вы уменьшили проблему до, скажем, 10 строк кода. Это больше для вас, но меньше для всех остальных. Я также обнаружил, что иногда сам процесс сокращения сам отвечает на проблему. Просто мысль. – Ant