Skip to content

Commit

Permalink
Enhance requestAddress by looping through poll responses (#238)
Browse files Browse the repository at this point in the history
* Enhance request address

- When beginning to request an address, the requesting node will gather poll responses. Utilize all poll responses: If an address request fails, continue looping through available poll responses until all address requests at that level have been exhausted

* Move gotResponse variable

- Move gotResponse variable into loop so it defaults to 0

* - Further improve requestAddress

- Per @2bndy5 in #238
- Change debug prints: Remove millis calls and improve human readability
- Adjust timeout calculations to be calculated out of loop
- Change main polling loop per @2bndy5

* Mods per @2bndy5 in #238

- Use same timeout variable
- Add return 0 if 0 polls received
  • Loading branch information
TMRh20 authored Jun 9, 2024
1 parent 7c30deb commit f97a9bf
Showing 1 changed file with 45 additions and 44 deletions.
89 changes: 45 additions & 44 deletions RF24Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,49 +314,49 @@ bool ESBMesh<network_t, radio_t>::requestAddress(uint8_t level)
{
RF24NetworkHeader header(MESH_MULTICAST_ADDRESS, NETWORK_POLL);
//Find another radio, starting with level 0 multicast
IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Poll\n"), millis()));
IF_MESH_DEBUG(printf_P(PSTR("MSH Poll Level %d\n"), level));
network.multicast(header, 0, 0, level);

uint32_t timr = millis();
uint32_t timeout = millis() + 55;
#define MESH_MAXPOLLS 4
uint16_t contactNode[MESH_MAXPOLLS];
uint8_t pollCount = 0;

while (1) {
while (millis() < timeout && pollCount < MESH_MAXPOLLS) {
#if defined(MESH_DEBUG)
bool goodSignal = radio.testRPD();
#endif

if (network.update() == NETWORK_POLL) {

memcpy(&contactNode[pollCount], &network.frame_buffer[0], sizeof(uint16_t));
if (pollCount > 0 && contactNode[pollCount] != contactNode[pollCount - 1]) { //Drop duplicate polls to help prevent duplicate requests
++pollCount;
uint16_t contact = 0;
memcpy(&contact, &network.frame_buffer[0], sizeof(contact));

// Drop duplicate polls to help prevent duplicate requests
bool isDupe = false;
for (uint8_t i = 0; i < pollCount; ++i) {
if (contact == contactNode[i]) {
isDupe = true;
break;
}
}
else {
if (!isDupe) {
contactNode[pollCount] = contact;
++pollCount;
IF_MESH_DEBUG(printf_P(PSTR("MSH Poll %c -64dbm from 0%o \n"), (goodSignal ? '>' : '<'), contact));
}

IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Poll %c -64dbm\n"), millis(), (goodSignal ? '>' : '<')));
} // end if

if (millis() - timr > 55 || pollCount >= MESH_MAXPOLLS) {
if (!pollCount) {
IF_MESH_DEBUG(printf_P(PSTR("%u: MSH No poll from level %d\n"), millis(), level));
return 0;
}
else {
IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Poll OK\n"), millis()));
break;
}
}
MESH_CALLBACK
} // end while

IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Got poll from level %d count %d\n"), millis(), level, pollCount));
IF_MESH_DEBUG(printf_P(PSTR("MSH Polls from level %d: %d\n"), level, pollCount));

if (!pollCount) return 0;

bool gotResponse = 0;
for (uint8_t i = 0; i < pollCount; i++) {

bool gotResponse = 0;

// Request an address via the contact node
header.type = NETWORK_REQ_ADDRESS;
header.reserved = _nodeID;
Expand All @@ -365,49 +365,50 @@ bool ESBMesh<network_t, radio_t>::requestAddress(uint8_t level)
// Do a direct write (no ack) to the contact node. Include the nodeId and address.
network.write(header, 0, 0, contactNode[i]);

IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Request address from: 0%o\n"), millis(), contactNode[i]));
IF_MESH_DEBUG(printf_P(PSTR("MSH Request address from: 0%o\n"), contactNode[i]));

timr = millis();
timeout = millis() + 225;

while (millis() - timr < 225) {
while (millis() < timeout) {
if (network.update() == NETWORK_ADDR_RESPONSE) {
if (network.frame_buffer[7] == _nodeID) {
uint16_t newAddy = 0;
memcpy(&newAddy, &network.frame_buffer[sizeof(RF24NetworkHeader)], sizeof(newAddy));
uint16_t mask = 0xFFFF;
newAddy &= ~(mask << (3 * getLevel(contactNode[i]))); // Get the level of contact node. Multiply by 3 to get the number of bits to shift (3 per digit)
if (newAddy == contactNode[i]) { // Then shift the mask by this much, and invert it bitwise. Apply the mask to the newly received
i = pollCount; // address to evalute whether 'subnet' of the assigned address matches the contact node address.
gotResponse = 1;
gotResponse = 1; // address to evalute whether 'subnet' of the assigned address matches the contact node address.
break;
}
}
}
MESH_CALLBACK
}
} // end for

if (!gotResponse) {
return 0;
}
if (!gotResponse) {
continue;
}

uint16_t newAddress = 0;
memcpy(&newAddress, network.frame_buffer + sizeof(RF24NetworkHeader), sizeof(newAddress));
uint16_t newAddress = 0;
memcpy(&newAddress, network.frame_buffer + sizeof(RF24NetworkHeader), sizeof(newAddress));

IF_MESH_DEBUG(printf_P(PSTR("Set address 0%o rcvd 0%o\n"), mesh_address, newAddress));
mesh_address = newAddress;
IF_MESH_DEBUG(printf_P(PSTR("Set address: Current: 0%o New: 0%o\n"), mesh_address, newAddress));
mesh_address = newAddress;

radio.stopListening();
network.begin(mesh_address);
radio.stopListening();
network.begin(mesh_address);

// getNodeID() doesn't use auto-ack; do a double-check to manually retry 1 more time
if (getNodeID(mesh_address) != _nodeID) {
// getNodeID() doesn't use auto-ack; do a double-check to manually retry 1 more time
if (getNodeID(mesh_address) != _nodeID) {
beginDefault();
return 0;
if (getNodeID(mesh_address) != _nodeID) {
beginDefault();
continue;
}
}
}
return 1;
return 1;
} // end for

return 0;
}

/*****************************************************/
Expand Down Expand Up @@ -521,7 +522,7 @@ void ESBMesh<network_t, radio_t>::DHCP()

// Get the unique id of the requester (ID is in header.reserved)
if (!header.reserved || header.type != NETWORK_REQ_ADDRESS) {
IF_MESH_DEBUG(printf_P(PSTR("%u: MSH Invalid id or type rcvd\n"), millis()));
IF_MESH_DEBUG(printf_P(PSTR("MSH Invalid id or type rcvd\n")));
return;
}

Expand Down

0 comments on commit f97a9bf

Please sign in to comment.