Example #1
0
bool sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
{
	// Assemble the message
	uint8_t thisSequenceNumber = ++_lastSequenceNumber;
	uint8_t retries = 0;
	while (retries++ <= _retries)
	{
		setHeaderId(thisSequenceNumber);
//	setHeaderFlags(RH_FLAGS_NONE, RH_FLAGS_ACK); // Clear the ACK flag
		setHeaderFlags(RH_FLAGS_NONE); // Clear the ACK flag
		sendto(buf, len, address);
		waitPacketSent();

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

		if (retries > 1)
			_retransmissions++;
		unsigned long thisSendTime = millis(); // 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 * random(0, 256) / 256);
		int32_t timeLeft;
		while ((timeLeft = timeout - (millis() - thisSendTime)) > 0)
		{
			if (waitAvailableTimeout(timeLeft))
			{
				uint8_t from, to, id, flags;
				if (recvfrom(0, 0, &from, &to, &id, &flags)) // Discards the message
				{
					// Now have a message: is it our ACK?
					if (from == address && to == _thisAddress && (flags & RH_FLAGS_ACK) && (id == thisSequenceNumber))
					{
						// Its the ACK we are waiting for
						return true;
					}
					else if (!(flags & RH_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
			YIELD;
		}
		// Timeout exhausted, maybe retry
		YIELD;
	}
	// Retries exhausted
	return false;
}
Example #2
0
bool recvfromAckTimeout(uint8_t* buf, uint8_t* len, uint16_t timeout, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
{
	unsigned long starttime = millis();
	int32_t timeLeft;
	while ((timeLeft = timeout - (millis() - starttime)) > 0)
	{
		if (waitAvailableTimeout(timeLeft))
		{
			if (recvfromAck(buf, len, from, to, id, flags))
				return true;
		} YIELD;
	}
	return false;
}
Example #3
0
// Block until something is available
void HardwareSerial::waitAvailable()
{
    waitAvailableTimeout(0); // 0 = Wait forever
}
Example #4
0
bool RHReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
{
    // Assemble the message
    uint8_t thisSequenceNumber = ++_lastSequenceNumber;
    uint8_t retries = 0;
    while (retries++ <= _retries)
    {
	setHeaderId(thisSequenceNumber);

        // Set and clear header flags depending on if this is an
        // initial send or a retry.
        uint8_t headerFlagsToSet = RH_FLAGS_NONE;
        // Always clear the ACK flag
        uint8_t headerFlagsToClear = RH_FLAGS_ACK;
        if (retries == 1) {
            // On an initial send, clear the RETRY flag in case
            // it was previously set
            headerFlagsToClear |= RH_FLAGS_RETRY;
        } else {
            // Not an initial send, set the RETRY flag
            headerFlagsToSet = RH_FLAGS_RETRY;
        }
        setHeaderFlags(headerFlagsToSet, headerFlagsToClear);

	sendto(buf, len, address);
	waitPacketSent();

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

	if (retries > 1)
	    _retransmissions++;
	unsigned long thisSendTime = millis(); // 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
#if (RH_PLATFORM == RH_PLATFORM_RASPI) // use standard library random(), bugs in random(min, max)
	uint16_t timeout = _timeout + (_timeout * (random() & 0xFF) / 256);
#else
	uint16_t timeout = _timeout + (_timeout * random(0, 256) / 256);
#endif
	int32_t timeLeft;
        while ((timeLeft = timeout - (millis() - thisSendTime)) > 0)
	{
	    if (waitAvailableTimeout(timeLeft))
	    {
		uint8_t from, to, id, flags;
		if (recvfrom(0, 0, &from, &to, &id, &flags)) // Discards the message
		{
		    // Now have a message: is it our ACK?
		    if (   from == address 
			   && to == _thisAddress 
			   && (flags & RH_FLAGS_ACK) 
			   && (id == thisSequenceNumber))
		    {
			// Its the ACK we are waiting for
			return true;
		    }
		    else if (   !(flags & RH_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
	    YIELD;
	}
	// Timeout exhausted, maybe retry
	YIELD;
    }
    // Retries exhausted
    return false;
}
Example #5
0
// Block until something is available
void RH_TCP::waitAvailable()
{
    waitAvailableTimeout(0); // 0 = Wait forever
}