Skip to content

Commit

Permalink
Per #14 add first/last fragment, debugging cleanup
Browse files Browse the repository at this point in the history
Per #14 and
e34a394#commitcomment-7727886
added NETWORK_FIRST_FRAGMENT
- Add total_fragments to RF24NetworkFrame
- Add error checking per discussion
- Modify debug to include FRG for fragment handling messages and RT for
routed messages
- Add SERIAL_DEBUG_MINIMAL to be changed as required for debugging new
features in RF24NetworkDEV
  • Loading branch information
TMRh20 committed Sep 11, 2014
1 parent cf2c29f commit a4b6076
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 49 deletions.
113 changes: 71 additions & 42 deletions RPi/RF24Network/RF24Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,16 @@ uint8_t RF24Network::update(void)

IF_SERIAL_DEBUG(printf_P("%u: MAC Received on %u %s\n\r",millis(),pipe_num,header.toString()));
if (len) {
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: Rcv MAC frame size %i\n",millis(),len););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: Rcv MAC frame ",millis()); const char* charPtr = reinterpret_cast<const char*>(frame_buffer); for (size_t i = 0; i < len; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG Rcv frame size %i\n",millis(),len););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG Rcv frame ",millis()); const char* charPtr = reinterpret_cast<const char*>(frame_buffer); for (size_t i = 0; i < len; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
}

// Throw it away if it's not a valid address
if ( !is_valid_address(header.to_node) ){
continue;
}

IF_SERIAL_DEBUG(printf_P("%u: MAC Valid frame from %i with size %i received.\n\r",millis(),header.from_node,len));
IF_SERIAL_DEBUG(printf_P("%u: MAC Valid payload from %i with size %i received.\n\r",millis(),header.from_node,len));

// Build the full frame
RF24NetworkFrame frame = RF24NetworkFrame(header,frame_buffer+sizeof(RF24NetworkHeader),len-sizeof(RF24NetworkHeader));
Expand All @@ -132,7 +132,7 @@ uint8_t RF24Network::update(void)
if ( header.to_node == node_address ){
if(res == NETWORK_ACK){
#ifdef SERIAL_DEBUG_ROUTING
printf_P(PSTR("MAC: Network ACK Rcvd\n"));
printf_P(PSTR("RT: Network ACK Rcvd\n"));
#endif
return NETWORK_ACK;
}
Expand All @@ -146,7 +146,7 @@ uint8_t RF24Network::update(void)
if(header.id != lastMultiMessageID){
if(multicastRelay){
#ifdef SERIAL_DEBUG_ROUTING
printf_P(PSTR("MAC: FWD multicast frame from 0%o to level %d\n"),header.from_node,multicast_level+1);
printf_P(PSTR("RT: FWD multicast frame from 0%o to level %d\n"),header.from_node,multicast_level+1);
#endif
write(levelToAddress(multicast_level)<<3,4);
}
Expand All @@ -155,7 +155,7 @@ uint8_t RF24Network::update(void)
}
#ifdef SERIAL_DEBUG_ROUTING
else{
printf_P(PSTR("MAC: Drop duplicate multicast frame %u from 0%o\n"),header.id,header.from_node);
printf_P(PSTR("RT: Drop duplicate multicast frame %u from 0%o\n"),header.id,header.from_node);
}
#endif
}else{
Expand Down Expand Up @@ -192,35 +192,45 @@ uint8_t RF24Network::update(void)
bool RF24Network::enqueue(RF24NetworkFrame frame) {
bool result = false;

if (frame.header.fragment_id > 1 && frame.header.type == NETWORK_MORE_FRAGMENTS) {

if (frame.header.fragment_id > 1 && (frame.header.type == NETWORK_MORE_FRAGMENTS || frame.header.type== NETWORK_FIRST_FRAGMENT)){
//Set the more fragments flag to indicate a fragmented frame
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: MAC fragmented payload of size %i Bytes with fragmentID '%i' received.\n\r",millis(),frame.message_size,frame.header.fragment_id););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG fragmented payload of size %i Bytes with fragmentID '%i' received.\n\r",millis(),frame.message_size,frame.header.fragment_id););

//Append payload
appendFragmentToFrame(frame);
result = true;

} else if (frame.header.fragment_id == 1 && frame.header.type == NETWORK_LAST_FRAGMENT) {
//Set the last fragment flag to indicate the last fragment
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: MAC Last fragment with size %i Bytes and fragmentID '%i' received.\n\r",millis(),frame.message_size,frame.header.fragment_id););

IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG Last fragment with size %i Bytes and fragmentID '%i' received.\n\r",millis(),frame.message_size,frame.header.fragment_id););
//Append payload
appendFragmentToFrame(frame);

IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET Enqueue assembled frame @%x "),millis(),frame_queue.size()));
//Push the assembled frame in the frame_queue and remove it from cache
frame_queue.push( frameFragmentsCache[ std::make_pair(frame.header.from_node,frame.header.id) ] );

//Push the assembled frame in the frame_queue and remove it from cache
// If total_fragments == 0, we are finished
if(!frame.total_fragments){
frame_queue.push( frameFragmentsCache[ std::make_pair(frame.header.from_node,frame.header.id) ] );
}else{
IF_SERIAL_DEBUG_MINIMAL( printf("%u: NET Dropped frame missing %d fragments\n",millis(),frame.total_fragments ););
}
frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) );

result = true;

} else {
} else if(frame.header.type < 128){

This comment has been minimized.

Copy link
@reixd

reixd Sep 11, 2014

Contributor

What do you think of defining a constant do describe this value?

define MIN_USER_HEADER_TYPE 1

define MAX_USER_HEADER_TYPE 128

This comment has been minimized.

Copy link
@TMRh20

TMRh20 Sep 11, 2014

Author Member

Haha, I think it would follow standards a bit better than I do sometimes. Feel free to make the change, or I can add it in a later commit.

IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET Enqueue @%x "),millis(),frame_queue.size()));

// Copy the current frame into the frame queue
frame_queue.push(frame);
result = true;
}else{
IF_SERIAL_DEBUG_MINIMAL( printf("%u: FRG Received unknown or system header type %d \n",millis(),frame.header.type); );
}


if (result) {
IF_SERIAL_DEBUG(printf("ok\n\r"));
Expand All @@ -234,36 +244,48 @@ bool RF24Network::enqueue(RF24NetworkFrame frame) {
/******************************************************************/

void RF24Network::appendFragmentToFrame(RF24NetworkFrame frame) {

if (frameFragmentsCache.count(std::make_pair(frame.header.from_node,frame.header.id)) == 0 ) {

//If there is an un-finished fragment:
for (std::map<std::pair<uint16_t, uint16_t>, RF24NetworkFrame>::iterator it=frameFragmentsCache.begin(); it!=frameFragmentsCache.end(); ++it){
if( it->first.first == frame.header.from_node){
frameFragmentsCache.erase( it );
//printf("Map Size: %d\n",frameFragmentsCache.size());
break;
}
}

//This is the first of many fragments
frameFragmentsCache[ std::make_pair(frame.header.from_node,frame.header.id) ] = frame;
// If this is the first of many fragments.
if(frame.header.type == NETWORK_FIRST_FRAGMENT){
// Decrement the stored total_fragments counter
frame.total_fragments = frame.header.fragment_id-1;
// Cache the fragment
frameFragmentsCache[ std::make_pair(frame.header.from_node,frame.header.id) ] = frame;
}else{
IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRG Dropping all fragments for frame id:%d, missing first fragment(s).\n",millis(),frame.header.id););
}

} else {
//We have at least received one fragments.
//Append payload
RF24NetworkFrame *f = &(frameFragmentsCache[ std::make_pair(frame.header.from_node,frame.header.id) ]);

//Error checking for missed fragments and payload size
if(frame.header.fragment_id != f->header.fragment_id-1){
if(frame.header.fragment_id > f->header.fragment_id){
IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRG Duplicate or out of sequence frame %d, expected %d. Cleared.\n",millis(),frame.header.fragment_id,f->header.fragment_id););
}else{
frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) );
IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRG Out of sequence frame %d, expected %d. Cleared.\n",millis(),frame.header.fragment_id,f->header.fragment_id-1););
}
return;
}
if(frame.message_size + f->message_size > MAX_PAYLOAD_SIZE){
frameFragmentsCache.erase( std::make_pair(frame.header.from_node,frame.header.id) );
printf("cleared corrupt frame\n");
}else{
IF_SERIAL_DEBUG_MINIMAL(printf("%u: FRM Payload of %d exceeds MAX_PAYLOAD_SIZE %d Bytes. Frame dropped\n",millis(),frame.message_size + f->message_size,MAX_PAYLOAD_SIZE););
return;
}

memcpy(f->message_buffer+f->message_size, frame.message_buffer, frame.message_size);
//Increment message size
f->message_size += frame.message_size;
//Update header
f->header = frame.header;
}
//Update Total fragments
f->total_fragments--;

}
}

Expand Down Expand Up @@ -312,9 +334,9 @@ size_t RF24Network::read(RF24NetworkHeader& header,void* message, size_t maxlen)
memcpy(&header,&(frame.header),sizeof(RF24NetworkHeader));
memcpy(message,frame.message_buffer,bufsize);

IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET message size %i\n",millis(),frame.message_size););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET message ",millis()); const char* charPtr = reinterpret_cast<const char*>(message); for (size_t i = 0; i < bufsize; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET readed %s\n\r"),millis(),header.toString()));
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message size %i\n",millis(),frame.message_size););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message ",millis()); const char* charPtr = reinterpret_cast<const char*>(message); for (size_t i = 0; i < bufsize; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
IF_SERIAL_DEBUG(printf_P(PSTR("%u: NET read %s\n\r"),millis(),header.toString()));

frame_queue.pop();
}
Expand Down Expand Up @@ -358,7 +380,7 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le

//Check payload size
if (len > MAX_PAYLOAD_SIZE) {
IF_SERIAL_DEBUG(printf("%u: NET write message failed. Given 'len' is bigger than the MAX Payload size of %i\n\r",millis(),MAX_PAYLOAD_SIZE););
IF_SERIAL_DEBUG(printf("%u: NET write message failed. Given 'len' is bigger than the MAX Payload size %i\n\r",millis(),MAX_PAYLOAD_SIZE););
return false;
}

Expand All @@ -383,8 +405,9 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le
uint8_t fragment_id = 1 + ((len - 1) / max_frame_payload_size); //the number of fragments to send = ceil(len/max_frame_payload_size)
uint8_t msgCount = 0;

IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET total message fragments %i\n\r",millis(),fragment_id););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG Total message fragments %i\n\r",millis(),fragment_id););

bool firstFrag = 1;
//Iterate over the payload chuncks
// Assemble a new message, copy and fill out the header
// Try to send this message
Expand All @@ -400,29 +423,35 @@ bool RF24Network::write(RF24NetworkHeader& header,const void* message, size_t le
if (fragment_id == 1) {
fragmentHeader.type = NETWORK_LAST_FRAGMENT; //Set the last fragment flag to indicate the last fragment
} else {
fragmentHeader.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame
if(firstFrag == 1){
fragmentHeader.type = NETWORK_FIRST_FRAGMENT;
firstFrag = 0;
}else{
fragmentHeader.type = NETWORK_MORE_FRAGMENTS; //Set the more fragments flag to indicate a fragmented frame
}
}

size_t offset = msgCount*max_frame_payload_size;
size_t fragmentLen = std::min(len-offset,max_frame_payload_size);

IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET try to transmit fragmented payload of size %i Bytes with fragmentID '%i'\n\r",millis(),fragmentLen,fragment_id););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG try to transmit fragmented payload of size %i Bytes with fragmentID '%i'\n\r",millis(),fragmentLen,fragment_id););

//Try to send the payload chunk with the copied header
bool ok = _write(fragmentHeader,message+offset,fragmentLen,writeDirect);
if (!ok) {
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET message transmission with fragmentID '%i' failed. Abort.\n\r",millis(),fragment_id););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message transmission with fragmentID '%i' failed. Abort.\n\r",millis(),fragment_id););
txSuccess = false;
break;
}
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: NET message transmission with fragmentID '%i' sucessfull.\n\r",millis(),fragment_id););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG message transmission with fragmentID '%i' sucessfull.\n\r",millis(),fragment_id););

//Message was successful sent
//Check and modify counters
fragment_id--;
msgCount++;
}
int frag_delay = int(len/16); delay( std::min(frag_delay,15) );
int frag_delay = int(len/32);
delay( std::min(frag_delay,15) );
//Return true if all the chuncks where sent successfuly
//else return false
IF_SERIAL_DEBUG(printf("%u: NET total message fragments sent %i. txSuccess ",millis(),msgCount); printf("%s\n\r", txSuccess ? "YES" : "NO"););
Expand All @@ -447,8 +476,8 @@ bool RF24Network::_write(RF24NetworkHeader& header,const void* message, size_t l
if (frame_size)
{
// IF_SERIAL_DEBUG(const uint16_t* i = reinterpret_cast<const uint16_t*>(message);printf_P(PSTR("%u: NET message %04x\n\r"),millis(),*i));
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: MAC frame size %i\n",millis(),frame_size););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: MAC frame ",millis()); const char* charPtr = reinterpret_cast<const char*>(frame_buffer); for (size_t i = 0; i < frame_size; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG frame size %i\n",millis(),frame_size););
IF_SERIAL_DEBUG_FRAGMENTATION(printf("%u: FRG frame ",millis()); const char* charPtr = reinterpret_cast<const char*>(frame_buffer); for (size_t i = 0; i < frame_size; i++) { printf("%02X ", charPtr[i]); }; printf("\n\r"));
}


Expand Down Expand Up @@ -540,7 +569,7 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo)
frame_buffer[2] = frame_buffer[0]; frame_buffer[3] = frame_buffer[1];
write(fromAddress,1);
#if defined (SERIAL_DEBUG_ROUTING)
printf("MAC: Route OK to 0%o ACK sent to 0%o\n",to_node,fromAddress);
printf("RT Route OK to 0%o ACK sent to 0%o\n",to_node,fromAddress);
#endif
}

Expand All @@ -565,7 +594,7 @@ bool RF24Network::write(uint16_t to_node, uint8_t directTo)
if(millis() - reply_time > routeTimeout){
ok=0;
#ifdef SERIAL_DEBUG_ROUTING
printf_P(PSTR("%u: MAC Network ACK fail from 0%o via 0%o on pipe %x\n\r"),millis(),logicalAddress,send_node,send_pipe);
printf_P(PSTR("%u: RT Network ACK fail from 0%o via 0%o on pipe %x\n\r"),millis(),logicalAddress,send_node,send_pipe);
#endif
break;
}
Expand Down
12 changes: 7 additions & 5 deletions RPi/RF24Network/RF24Network.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
//Network header message types
#define NETWORK_ACK_REQUEST 128
#define NETWORK_ACK 129
#define NETWORK_MORE_FRAGMENTS 130
#define NETWORK_LAST_FRAGMENT 131
#define NETWORK_FIRST_FRAGMENT 130
#define NETWORK_MORE_FRAGMENTS 131
#define NETWORK_LAST_FRAGMENT 132



class RF24;
Expand Down Expand Up @@ -104,7 +106,7 @@ struct RF24NetworkFrame
RF24NetworkHeader header; /**< Header which is sent with each message */
size_t message_size; /**< The size in bytes of the payload length */
uint8_t message_buffer[MAX_PAYLOAD_SIZE]; /**< Vector to put the frame payload that will be sent/received over the air */

uint8_t total_fragments; /**<Total number of expected fragments*/
/**
* Default constructor
*
Expand All @@ -118,7 +120,7 @@ struct RF24NetworkFrame
* Use this constructor to create a frame with header and payload and then send a message
*/
RF24NetworkFrame(uint16_t _to, unsigned char _type = 0, const void* _message = NULL, size_t _len = 0) :
header(RF24NetworkHeader(_to,_type)), message_size(_len) {
header(RF24NetworkHeader(_to,_type)), message_size(_len), total_fragments(0) {
if (_message && _len) {
memcpy(message_buffer,_message,_len);
}
Expand All @@ -130,7 +132,7 @@ struct RF24NetworkFrame
* Use this constructor to create a frame with header and payload and then send a message
*/
RF24NetworkFrame(RF24NetworkHeader& _header, const void* _message = NULL, size_t _len = 0) :
header(_header), message_size(_len) {
header(_header), message_size(_len), total_fragments(0) {
if (_message && _len) {
memcpy(message_buffer,_message,_len);
}
Expand Down
11 changes: 9 additions & 2 deletions RPi/RF24Network/RF24Network_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
/********** USER CONFIG **************/

//#define RF24NetworkMulticast
//#define SERIAL_DEBUG //Change #undef to #define for debug
#define SERIAL_DEBUG_ROUTING
//#define SERIAL_DEBUG //Change #undef to #define for full debug
#define SERIAL_DEBUG_MINIMAL //Enable minimal debugging
//#define SERIAL_DEBUG_ROUTING
//#define SERIAL_DEBUG_FRAGMENTATION

/*************************************/
Expand All @@ -36,6 +37,12 @@
#define IF_SERIAL_DEBUG(x)
#endif

#if defined (SERIAL_DEBUG_MINIMAL)
#define IF_SERIAL_DEBUG_MINIMAL(x) ({x;})
#else
#define IF_SERIAL_DEBUG_MINIMAL(x)
#endif

#if defined (SERIAL_DEBUG_FRAGMENTATION)
#define IF_SERIAL_DEBUG_FRAGMENTATION(x) ({x;})
#else
Expand Down

0 comments on commit a4b6076

Please sign in to comment.