- Main Page
- Classes
- Files

# RF22ReliableDatagram.h

    00001 // RF22ReliableDatagram.h
    00002 //
    00003 // Author: Mike McCauley (mikem@open.com.au)
    00004 // Copyright (C) 2011 Mike McCauley
    00005 // $Id: RF22ReliableDatagram.h,v 1.6 2011/02/15 01:18:03 mikem Exp $
    00006
    00007 #ifndef RF22ReliableDatagram_h
    00008 #define RF22ReliableDatagram_h
    00009
    00010 #include <RF22Datagram.h>
    00011
    00012 // The acknowledgement bit in the FLAGS
    00013 #define RF22_FLAGS_ACK 0x80
    00014
    00015 /////////////////////////////////////////////////////////////////////
    00016 /// \class RF22ReliableDatagram RF22ReliableDatagram.h <RF22ReliableDatagram.h>
    00017 /// \brief RF22 subclass for sending addressed, acknowledged, retransmitted datagrams.
    00018 ///
    00019 /// Extends RF22Datagram to define addressed, reliable datagrams with acknowledgement and retransmission.
    00020 /// Based on RF22Datagram, adds flags and sequence numbers. RF22ReliableDatagram is reliable in the sense
    00021 /// that messages are acknowledged, and unacknowledged messages are retransmitted until acknowledged or the
    00022 /// retries are exhausted.
    00023 /// When addressed messages are sent (by sendtoWait()), it will wait for an ack, and retransmit
    00024 /// after timeout until an ack is received or retries are exhausted.
    00025 /// When addressed messages are collected by the application (by recvfromAck()),
    00026 /// an acknowledgement is automatically sent.
    00027 ///
    00028 /// The retransmit timeout is randomly varied between timeout and timeout*2 to prevent collisions on all
    00029 /// retries when  2 nodes happen to start sending at the same time .
    00030 ///
    00031 /// Each new message sent by sendtoWait() has its ID incremented.
    00032 ///
    00033 /// An ack consists of a message with:
    00034 /// - TO set to the from address of the original message
    00035 /// - FROM set to this node address
    00036 /// - ID set to the ID of the original message
    00037 /// - FLAGS with the RF22_FLAGS_ACK bit set
    00038 ///
    00039 /// Part of the Arduino RF22 library for operating with HopeRF RF22 compatible transceivers
    00040 /// (see http://www.hoperf.com)
    00041 class RF22ReliableDatagram : public RF22Datagram
    00042 {
    00043 public:
    00044     /// Constructor.
    00045     /// \param[in] thisAddress The address to assign to this node. Defaults to 0
    00046     /// \param[in] slaveSelectPin the Arduino pin number of the output to use to select the RF22 before
    00047     /// accessing it
    00048     /// \param[in] interrupt The interrupt number to use. Default is interrupt 0 (Arduino input pin 2)
    00049     RF22ReliableDatagram(uint8_t thisAddress = 0, uint8_t slaveSelectPin = 10, uint8_t interrupt = 0);
    00050
    00051     /// Sets the minimum retransmit timeout. If sendtoWait is waiting for an ack
    00052     /// longer than this time (in milliseconds),
    00053     /// it will retransmit the message. Defaults to 200ms. The timeout is measured from the end of
    00054     /// transmission of the message. It must be at least longer than the the transmit
    00055     /// time of the acknowledgement (6 octets) plus the latency/poll time of the receiver.
    00056     /// The actual timeout is randomly varied between timeout and timeout*2.
    00057     /// \param[in] timeout The new timeout period in milliseconds
    00058     void setTimeout(uint16_t timeout);
    00059
    00060     /// Sets the max number of retries. Defaults to 3. If set to 0, the message will only be sent once.
    00061     /// sendtoWait will give up and return false if there is no ack received after all transmissions time out.
    00062     /// param[in] retries The maximum number a retries.
    00063     void setRetries(uint8_t retries);
    00064
    00065     /// Send the message and waits for an ack. Returns true if an acknowledgement is received.
    00066     /// Synchronous: any message other than the desired ACK received while waiting is discarded.
    00067     /// Blocks until an ACK is received or all retries are exhausted (ie up to retries*timeout milliseconds).
    00068     /// \param[in] address The address to send the message to.
    00069     /// \param[in] buf Pointer to the binary message to send
    00070     /// \param[in] len Number of octets to send
    00071     /// \return true if the message was transmitted and an acknowledgement was received.
    00072     boolean sendtoWait(uint8_t* buf, uint8_t len, uint8_t address);
    00073
    00074     /// If there is a valid message available for this node, send an acknowledgement to the SRC
    00075     /// address (blocking until this is complete), then copy the message to buf and return true
    00076     /// else return false.
    00077     /// If a message is copied, *len is set to the length..
    00078     /// If from is not NULL, the SRC address is placed in *from.
    00079     /// If to is not NULL, the DEST address is placed in *to.
    00080     /// This is the preferred function for getting messages addressed to this node.
    00081     /// If the message is not a broadcast, acknowledge to the sender before returning.
    00082     /// You should be sure to call this function frequently enough to not miss any messages
    00083     /// It is recommended that you call it in your main loop.
    00084     /// \param[in] buf Location to copy the received message
    00085     /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
    00086     /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address
    00087     /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address
    00088     /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
    00089     /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
    00090     /// (not just those addressed to this node).
    00091     /// \return true if a valid message was copied to buf
    00092     boolean recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from = NULL, uint8_t* to = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
    00093
    00094     /// Similar to recvfromAck(), this will block until either a valid message available for this node
    00095     /// or the timeout expires. Starts the receiver automatically.
    00096     /// You should be sure to call this function frequently enough to not miss any messages
    00097     /// It is recommended that you call it in your main loop.
    00098     /// \param[in] buf Location to copy the received message
    00099     /// \param[in,out] len Available space in buf. Set to the actual number of octets copied.
    00100     /// \param[in] timeout Maximum time to wait in milliseconds
    00101     /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address
    00102     /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address
    00103     /// \param[in] id If present and not NULL, the referenced uint8_t will be set to the ID
    00104     /// \param[in] flags If present and not NULL, the referenced uint8_t will be set to the FLAGS
    00105     /// (not just those addressed to this node).
    00106     /// \return true if a valid message was copied to buf
    00107     boolean recvfromAckTimeout(uint8_t* buf, uint8_t* len,  uint16_t timeout, uint8_t* from = NULL, uint8_t* to = NULL, uint8_t* id = NULL, uint8_t* flags = NULL);
    00108
    00109     /// Returns the number of retransmissions
    00110     /// we have had to send
    00111     /// \return The number of retransmissions since initialisation.
    00112     uint16_t retransmissions();
    00113
    00114 protected:
    00115     /// Send an ACK for the message id to the given from address
    00116     /// Blocks until the ACK has been sent
    00117     void acknowledge(uint8_t id, uint8_t from);
    00118
    00119     /// Checks whether the message currently in the Rx buffer is a new message, not previously received
    00120     /// based on the from address and the sequence.  If it is new, it is acknowledged and returns true
    00121     /// \return true if there is a message received and it is a new message
    00122     boolean haveNewMessage();
    00123
    00124 private:
    00125     /// Count of retransmissions we have had to send
    00126     uint16_t _retransmissions;
    00127
    00128     /// The last sequence number to be used
    00129     /// Defaults to 0
    00130     uint8_t _lastSequenceNumber;
    00131
    00132     // Retransmit timeout (milliseconds)
    00133     /// Defaults to 200
    00134     uint16_t _timeout;
    00135
    00136     // Retries (0 means one try only)
    00137     /// Defaults to 3
    00138     uint8_t _retries;
    00139
    00140     /// Array of the last seen sequence number indexed by node address that sent it
    00141     /// It is used for duplicate detection. Duplicated messages are re-acknowledged when received
    00142     /// (this is generally due to lost ACKs, causing the sender to retransmit, even though we have already
    00143     /// received that message)
    00144     uint8_t _seenIds[256];
    00145
    00146
    00147 };
    00148
    00149 #endif
    00150