LowPowerLab Forum

Hardware support => Moteino => Topic started by: overlord on October 26, 2016, 02:43:57 PM

Title: How to enforce and read ACK? [solved]
Post by: overlord on October 26, 2016, 02:43:57 PM
Hello,

mayeb a stupid question, but how do I enforce an ACK by the sender from the receiver.
And how can I read the ACK? Lets say the receiver responds with some session Key?
Best Regards,
Rene
Title: Re: How to enforce and read ACK?
Post by: Felix on October 26, 2016, 04:33:50 PM
Look at the many RFM69 library examples. There is no ACK for an ACK.
Actually an ACK is just a regular (empty payload by default) packet with a special bit=TRUE which tells the sender the sent message was received.
You typically just use sendWithRetry(...) which allows you to retry a message several times (overridable) to ensure it is delivered.
A listening node that sees the ACK request bit = TRUE, will have to respond with an ACK packet.
If the link is good a single exchange will ensure the packet is delivered and ACK is returned to sender.
The end node can always send it's own packet and request an ACK from the main node, there is no constraint on who can send or request ACKs.
Title: Re: How to enforce and read ACK?
Post by: TomWS on October 26, 2016, 08:13:47 PM
Quote from: overlord on October 26, 2016, 02:43:57 PM
Hello,

mayeb a stupid question, but how do I enforce an ACK by the sender from the receiver.
And how can I read the ACK? Lets say the receiver responds with some session Key?
Best Regards,
Rene
Not a stupid question at all.  There is virtually no documentation on ACK protocol so the 'good news is' you could invent your own.   The RFM69_ATC library uses ACK to send back the RSSI from the sender's last packet so that the original sender knows how much signal is getting through and adjust accordingly.  In another library, ACK is used to include a packet that tells the sender that the other end point has 'something' for it.  This allows the sender to contact the other end point and ask for whatever it may have to send, setting up a convenient two way conversation.

The method is simple, when a receiver sees a 'requestACK', it can send back a full packet along with the 'ACK'.  The original sender will be able to read that in the radio.DATA/radio.DATALEN tuple received with the ACK.

Tom

Title: Re: How to enforce and read ACK?
Post by: ssmall on November 13, 2016, 03:09:00 PM
I am trying to do something similar in that I am sending data from a weather station to a gateway that receives the data.  The weather station uses radio.sendWithRetry.  The gateway receives the data and sends an ACK with no data and the weather station receives the ACK.  That all works great.  What I would like to do now is send data in the ACK and have the weather station receive the data in the ACK from the gateway.  So far I have not been able to receive the data in the ACK.

What am I missing?  radio.DATALEN is always zero.

Gateway code snippet

    if (radio.ACKRequested())
    {
        radio.sendACK("RST");
    }


Weather station code snippet

    if (radio.sendWithRetry(GATEWAYID, (const void*)(&remoteWeather),
                            sizeof(remoteWeather), 2, 75))
    {
      Serial.println("ACK received");

      Serial.println(radio.DATALEN);

      // Did a command to reset the rain amount arrive
      if (radio.DATALEN == 3)
      {
        Serial.println("ACK Data");
        if (radio.DATA[0]=='R' && radio.DATA[1]=='S' && radio.DATA[2]=='T')
        {
          // Reset the rain amount to zero
          rainAmount = 0.0;
        }
      }
    }
Title: Re: How to enforce and read ACK?
Post by: TomWS on November 13, 2016, 06:37:06 PM
To send data back with an ACK (and receive it) here is what I do:

On the Gateway side:

   radio.sendACK(&reqSomething,reqSomething.h.len);  // note that my packets have a header that includes a length field...


On the receive side:

  rc = radio.sendWithRetry(to, pkt, pkt->len);
  if (rc)
  {
    noInterrupts();  // this is necessary to prevent loss of data while copying
    // tranmission ok, see if any data was Ack'd
    if (radio.DATALEN && radio.DATALEN==radio.DATA[0]) // got a valid packet?  (validates packet if length field matches)
    {
      // 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;
  }



Tom
Title: Re: How to enforce and read ACK?
Post by: ssmall on November 13, 2016, 08:31:13 PM
Tom,

Thanks for the reply.  I can't believe I missed sending the length of the string.  :-[
I had been staring at the sendACK function for a 1/2 hr wondering why the string in the ACK wasn't show up!
I am receiving the data in the ACK now and I switched my code to copy the data to another variable.

Thanks!