Author Topic: Sending data back with ACK?  (Read 2783 times)

syrinxtech

  • Sr. Member
  • ****
  • Posts: 347
  • Country: us
    • Syrinx Technologies
Sending data back with ACK?
« on: December 19, 2015, 04:45:25 AM »
Maybe I'm missing something obvious, but I was trying to find an example of where somebody sends data back with the ACK.  My g/w node is sending a packet to the node requesting that it turn on a specific port (could be a relay, LED, etc.).  I want to make sure that the node does in fact perform that act so I'm doing a quick digitalWrite/digitalRead on the requested port.  I want to be able to send the data from the digitalRead back in the ACK packet.  I see in the RFM69 code where you are allowed to send a buffer of data back in the ACK response.

What I'm conceptually missing is how you detect and extract the data contained in the ACK packet.  I'm sure I'm missing something fundamental but any pointers would be appreciated.


TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: Sending data back with ACK?
« Reply #1 on: December 19, 2015, 08:15:08 AM »
Maybe I'm missing something obvious, but I was trying to find an example of where somebody sends data back with the ACK.  My g/w node is sending a packet to the node requesting that it turn on a specific port (could be a relay, LED, etc.).  I want to make sure that the node does in fact perform that act so I'm doing a quick digitalWrite/digitalRead on the requested port.  I want to be able to send the data from the digitalRead back in the ACK packet.  I see in the RFM69 code where you are allowed to send a buffer of data back in the ACK response.

What I'm conceptually missing is how you detect and extract the data contained in the ACK packet.  I'm sure I'm missing something fundamental but any pointers would be appreciated.
Sure, do it all the time...  Try this...

Code: [Select]
      rc = radio.sendWithRetry(to, &devDescriptor, devDescriptor.h.len);
      return AckCheck(rc);
...

/******************************************************************************
*
*   AckCheck() - local method to check to see if there is any AckData and save it locally if there is.
*
******************************************************************************/
bool AckCheck(bool rc)
{
  if (rc)
  {
    noInterrupts();
    // tranmission ok, see if any data was Ack'd
    if (radio.DATALEN && radio.DATALEN==radio.DATA[0]) // got a valid packet?
    {
      // yup, save it
      for (int i=0; i<radio.DATALEN; i++)
        sendAckData[i] = radio.DATA[i];
    }
      else
        sendAckData[0]=0;
    interrupts();
  } else
  {
    sendAckData[0]=0;
  }
  return rc;
}

/******************************************************************************
*
*   getAckData() - return ptr to locally saved ack data
*
******************************************************************************/
byte *getAckData(void)
{
  if (sendAckData[0]) return &sendAckData[0];
  return NULL;
}


The data comes in with the ACK and is picked up by the receiveDone called from sendWithRetry(). 

Tom

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Sending data back with ACK?
« Reply #2 on: December 19, 2015, 10:34:33 AM »
An ACK packet is just like any packet, the only exception being there is a bit set in one of the header bytes to indicate it's an ACK. Otherwise it can have a payload.
Adding to the code Tom shared, there's a bunch of sendACK() functions used in the WirelessHex library. In fact all you have to do is pass your string/buffer and the length you want to send.
Note that you will need to call sendACK before another packet from another node is received. Usually ACKs are meant to be sent as soon as possible after a packet is received, and not after some random time. That's another particularity of ACKs.

syrinxtech

  • Sr. Member
  • ****
  • Posts: 347
  • Country: us
    • Syrinx Technologies
Re: Sending data back with ACK?
« Reply #3 on: January 01, 2016, 10:26:47 AM »
Maybe I'm missing something obvious, but I was trying to find an example of where somebody sends data back with the ACK.  My g/w node is sending a packet to the node requesting that it turn on a specific port (could be a relay, LED, etc.).  I want to make sure that the node does in fact perform that act so I'm doing a quick digitalWrite/digitalRead on the requested port.  I want to be able to send the data from the digitalRead back in the ACK packet.  I see in the RFM69 code where you are allowed to send a buffer of data back in the ACK response.

What I'm conceptually missing is how you detect and extract the data contained in the ACK packet.  I'm sure I'm missing something fundamental but any pointers would be appreciated.

Sure, do it all the time...  Try this...

Code: [Select]
      rc = radio.sendWithRetry(to, &devDescriptor, devDescriptor.h.len);
      return AckCheck(rc);
...

/******************************************************************************
*
*   AckCheck() - local method to check to see if there is any AckData and save it locally if there is.
*
******************************************************************************/
bool AckCheck(bool rc)
{
  if (rc)
  {
    noInterrupts();
    // tranmission ok, see if any data was Ack'd
    if (radio.DATALEN && radio.DATALEN==radio.DATA[0]) // got a valid packet?
    {
      // yup, save it
      for (int i=0; i<radio.DATALEN; i++)
        sendAckData[i] = radio.DATA[i];
    }
      else
        sendAckData[0]=0;
    interrupts();
  } else
  {
    sendAckData[0]=0;
  }
  return rc;
}

/******************************************************************************
*
*   getAckData() - return ptr to locally saved ack data
*
******************************************************************************/
byte *getAckData(void)
{
  if (sendAckData[0]) return &sendAckData[0];
  return NULL;
}


The data comes in with the ACK and is picked up by the receiveDone called from sendWithRetry(). 

Tom

TomWS, thanks for the code.  I finally got around to testing it out today.  There is one line, however, that I don't understand:

if (radio.DATALEN && radio.DATALEN==radio.DATA[0])

This line always fails.  When I print out the values of radio.DATALEN and radio.DATA[0], I get the following:

radio.DATALEN = 30  (my message in the ACK is "Hello there, glad to meet you"
radio.DATA[0] = 72  (72 in decimal = 48 in hex = "H" (ASCII))

If I leave off the "&& radio.DATALEN==radio.DATA[0]", the code works great. 

Any thoughts on what I'm doing wrong?


TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: Sending data back with ACK?
« Reply #4 on: January 01, 2016, 03:18:51 PM »
TomWS, thanks for the code.  I finally got around to testing it out today.  There is one line, however, that I don't understand:

if (radio.DATALEN && radio.DATALEN==radio.DATA[0])

This line always fails.  When I print out the values of radio.DATALEN and radio.DATA[0], I get the following:

radio.DATALEN = 30  (my message in the ACK is "Hello there, glad to meet you"
radio.DATA[0] = 72  (72 in decimal = 48 in hex = "H" (ASCII))

If I leave off the "&& radio.DATALEN==radio.DATA[0]", the code works great. 

Any thoughts on what I'm doing wrong?
You're not doing anything wrong.  My code uses a packet encoding in which the header is:
Code: [Select]
struct MY_HEADER
{
  uint8_t
     len,      // length of the data block
     type;    // type of the data block
}
So, in my case, I can do the extra check for validity as the received length must always agree with the length of the aggregated data.  Since you don't use this encoding scheme, you can remove that test (as you have discovered).

Sorry for the misdirection...
Tom

syrinxtech

  • Sr. Member
  • ****
  • Posts: 347
  • Country: us
    • Syrinx Technologies
Re: Sending data back with ACK?
« Reply #5 on: January 01, 2016, 10:12:01 PM »
Thanks TomWS.  I was beginning to think I was losing my mind.....not that I might not be in the future but at least not now.