boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
{
    // Assemble the message
    uint8_t thisSequenceNumber = ++_lastSequenceNumber;

    Timer t;

    uint8_t retries = 0;
    while (retries++ <= _retries)
    {
        setHeaderId(thisSequenceNumber);
        setHeaderFlags(0);
        sendto(buf, len, address);
        waitPacketSent(3000);

        // Never wait for ACKS to broadcasts:
        if (address == RF22_BROADCAST_ADDRESS)
            return true;

        if (retries > 1)
            _retransmissions++;
        t.start();
        unsigned long thisSendTime = t.read_ms(); // Timeout does not include original transmit time


        // Compute a new timeout, random between _timeout and _timeout*2
    // This is to prevent collisions on every retransmit
        // if 2 nodes try to transmit at the same time
        uint16_t timeout = _timeout + (_timeout * (rand() % 100) / 100);
        while (t.read_ms() < (thisSendTime + timeout)) 
        {
            if (available()) {
                clearRxBuf(); // Not using recv, so clear it ourselves
                uint8_t from = headerFrom();
                uint8_t to = headerTo();
                uint8_t id = headerId();
                uint8_t flags = headerFlags();
                // Now have a message: is it our ACK?
                if (   from == address
                        && to == _thisAddress
                        && (flags & RF22_FLAGS_ACK)
            && (id == thisSequenceNumber))
        {
                    // Its the ACK we are waiting for
                    return true;
        }
        else if (   !(flags & RF22_FLAGS_ACK)
             && (id == _seenIds[from]))
        {
                    // This is a request we have already received. ACK it again
                    acknowledge(id, from);
                }
                // Else discard it
            }
            // Not the one we are waiting for, maybe keep waiting until timeout exhausted
        }
        // Timeout exhausted, maybe retry
    }
    return false;
}
示例#2
0
boolean RF22Datagram::recvfrom(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
{
    if (from)  *from =  headerFrom();
    if (to)    *to =    headerTo();
    if (id)    *id =    headerId();
    if (flags) *flags = headerFlags();
    return recv(buf, len);
}
bool RHDatagram::recvfrom(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
{
    if (_driver.recv(buf, len))
    {
	if (from)  *from =  headerFrom();
	if (to)    *to =    headerTo();
	if (id)    *id =    headerId();
	if (flags) *flags = headerFlags();
	return true;
    }
    return false;
}