00001 // HRFReliableDatagram.h 00002 // 00003 // Author: Mike McCauley (mikem@open.com.au) 00004 // Copyright (C) 2009 Mike McCauley 00005 // $Id: HRFReliableDatagram.h,v 1.1 2009/08/15 05:32:58 mikem Exp mikem $ 00006 00007 #ifndef HRFReliableDatagram_h 00008 #define HRFReliableDatagram_h 00009 00010 #include <HRFDatagram.h> 00011 00012 // Mask for the Sequence Number in FLAG/SQN 00013 #define HRF_SQN_MASK 0x7f 00014 00015 // The acknowledgement bit in the FLAG/SQN 00016 #define HRF_FLAG_ACK 0x80 00017 00018 // The maximum payload length 00019 #define HRF_MAX_RELIABLE_DATAGRAM_PAYLOAD HRF_MAX_DATAGRAM_PAYLOAD-1 00020 00021 ///////////////////////////////////////////////////////////////////// 00022 /// \class HRFReliableDatagram HRFReliableDatagram.h <HRFReliableDatagram.h> 00023 /// \brief Class for sending addressed, acknowledged, retransmitted datagrams. 00024 /// 00025 /// Extends HRFDatagram to define addressed, reliable datagrams with acknowledgement and retransmission. 00026 /// Based on HRFDatagram, adds flags and sequence numbers. HRFReliableDatagram is reliable in the sense 00027 /// that messages are acknowledged, and unacknowledged messages are retransmitted until acknowledged or the 00028 /// retries are exhausted. 00029 /// When addressed messages are collected by the application (recvfromAck), an acknowledgement is automatically sent. 00030 /// When addressed messages are sent (by sendtoWait), it will wait for an ack, and retransmit 00031 /// after timeout until an ack is received or retries are exhausted 00032 /// ReliableDatagrams have format LEN DEST SRC FLAG/SQN payload FCS-LO FCS-HI 00033 /// Low 7 bits of FLAG/SQN is the sequence number. Most significant bit is the ACK flag. 00034 /// 00035 /// Part of the Arduino HopeRF library for operating with HopeRF HM-TR transceivers 00036 /// (see http://www.hoperf.com) 00037 class HRFReliableDatagram : public HRFDatagram 00038 { 00039 private: 00040 /// The last sequence number to be used 00041 /// Defaults to 0 00042 uint8_t _lastSequenceNumber; 00043 00044 // Retransmit timeout (milliseconds) 00045 /// Defaults to 1000 00046 long _timeout; 00047 00048 // Retries (0 means one try only) 00049 /// Defaults to 3 00050 uint8_t _retries; 00051 00052 /// Array of the last seen sequence number indexed by node address that sent it 00053 /// It is used for duplicate detection. Duplicated messages are re-acknowledged when received 00054 /// (this is generally due to lost ACKs, causing the sender to retransmit, even though we have already 00055 /// received that message) 00056 uint8_t _seenSequenceNumbers[256]; 00057 00058 public: 00059 /// \param[in] serial The instance of HardwareSerial to use for IO. Defaults to &Serial, 00060 /// \param[in] thisAddress The address to assign to this node. Defaults to 0 00061 HRFReliableDatagram(HardwareSerial* serial = &Serial, uint8_t thisAddress = 0); 00062 00063 /// Sets the retransmit timeout. If sendtoWait is waiting for an ack longer than this time (in milliseconds), 00064 /// it will retransmit the message. Defaults to 1000ms. The timeout is measured from the beginning of 00065 /// transmission of the message. It must be longer than the transmit time of the request plus the transmit 00066 /// time of the acknowledgement (6 octets) plus the latency of the receiver. 00067 /// \param[in] timeout The new timeout period in milliseconds 00068 virtual void setTimeout(long timeout); 00069 00070 /// Sets the max number of retries. Defaults to 3. If set to 0, the message will only be sent once. 00071 /// sendtoWait will give up if there is no ack received after all transmissions time out. 00072 /// param[in] retries The maximum number a retries. 00073 virtual void setRetries(uint8_t retries); 00074 00075 /// Send the message and waits for an ack. Returns true if an acknowledgement is received. 00076 /// Synchronous: any message other than the desired ACK received while waiting is discarded. 00077 /// Blocks until an ACK is received or all retries are exhausted (ie up to retries*timeout milliseconds). 00078 /// \param[in] address The address to send the message to. 00079 /// \param[in] buf Pointer to the binary message to send 00080 /// \param[in] len Number of octets to send 00081 /// \return true if the message was transmitted and an acknowledgement is received. 00082 /// \return false if the message is too long (>HRF_MAX_DATAGRAM_PAYLOAD). 00083 virtual uint8_t sendtoWait(uint8_t address, uint8_t* buf, uint8_t len); 00084 00085 /// If there is a valid message available for this node, send an acknowledgement to the SRC 00086 /// address (blocking until this is complete), then copy the message to buf and return true 00087 /// else return false. 00088 /// If a message is copied, *len is set to the length.. 00089 /// If from is not NULL, the SRC address is placed in *from. 00090 /// If to is not NULL, the DEST address is placed in *to. 00091 /// This is the preferred function for getting messages addressed to this node. 00092 /// If the message is not a broadcast, acknowledge to the sender before returning. 00093 /// \param[in] buf Location to copy the received message 00094 /// \param[in] len Available space in buf. Set to the actual number of octets copied. 00095 /// \param[in] from If present and not NULL, the referenced uint8_t will be set to the SRC address 00096 /// \param[in] to If present and not NULL, the referenced uint8_t will be set to the DEST address 00097 virtual uint8_t recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* from = NULL, uint8_t* to = NULL); 00098 }; 00099 00100 #endif 00101