Я пытаюсь написать программу для загрузки файла в Arduino. Программа может открыть последовательный порт и получить данные от Arduino. Проблема возникает, когда я пытаюсь использовать функцию обратного вызова для функции в состоянии диаграммы состояния, происходит сбой программы.
Я никогда не использовал повышение раньше и решил, что это будет хорошая возможность попробовать это.
У меня есть объект диаграммы состояний с основными переходами, как так:
Idle; -> PortOpening; -> PortOpen; -> WaitForCurveChoiceConfirmation; -> Выбрать файл; -> WaitForFileReceive; -> Сравнить файлы; -> ЗакрытьПрограмма;
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. Arduino отправляет сообщение каждые несколько секунд, я использую обратный вызов, когда программа получает полное сообщение. Как только сообщение получено и вызван обратный вызов, моя программа падает.
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);» в процессе ReceivedData. Я уверен, что просто привязываю функцию неправильно или объявляю объект указатель на функцию неправильно.
Кто-нибудь может увидеть, где я иду не так?
Спасибо за вашу помощь
Мне удалось это решить. Это не имеет ничего общего с диаграммой состояний, связыванием или функционированием.
Это была моя ошибка с обратным вызовом. Я вызывал обратный вызов «полное сообщение получено», даже если ему не был назначен обратный вызов, и он был просто 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;
}
Других решений пока нет …