Skip to content

Commit

Permalink
ESPNOW: resubscribe to all topics after reconnection to bridge
Browse files Browse the repository at this point in the history
Ensures stability of subscriptions on client nodes.
  • Loading branch information
DavidB137 committed Feb 9, 2024
1 parent 161f720 commit 0a1d5cf
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 56 deletions.
2 changes: 2 additions & 0 deletions include/common/spsp_espnow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ namespace SPSP::LocalLayers::ESPNOW
*
* `rtndBr` and `connBr` may be the same pointers.
*
* Automatically resubscribes to all topics.
*
* @param rtndBr Retained bridge peer info (for reconnection)
* @param connBr Connected bridge peer info storage (if connection
* successful and `connBr` != nullptr)
Expand Down
118 changes: 62 additions & 56 deletions src/common/spsp_espnow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,83 +109,89 @@ namespace SPSP::LocalLayers::ESPNOW
bool ESPNOW::connectToBridge(BridgeConnInfoRTC* rtndBr,
BridgeConnInfoRTC* connBr)
{
// Mutex
const std::scoped_lock lock(m_mutex);
{ // Mutex
const std::scoped_lock lock(m_mutex);

if (rtndBr != nullptr) {
// Reconnect to retained bridge
m_bestBridge = *rtndBr;
m_wifi.setChannel(m_bestBridge.ch);
if (rtndBr != nullptr) {
// Reconnect to retained bridge
m_bestBridge = *rtndBr;
m_wifi.setChannel(m_bestBridge.ch);

if (connBr != nullptr) {
*connBr = *rtndBr;
}
if (connBr != nullptr) {
*connBr = *rtndBr;
}

SPSP_LOGI("Reconnected to bridge: %s",
m_bestBridge.addr.str.c_str());
SPSP_LOGI("Reconnected to bridge: %s",
m_bestBridge.addr.str.c_str());

return true;
}
return true;
}

SPSP_LOGD("Connect to bridge: connecting...");
SPSP_LOGD("Connect to bridge: connecting...");

// Get country restrictions
auto channelRestrictions = m_wifi.getChannelRestrictions();
uint8_t lowCh = channelRestrictions.low;
uint8_t highCh = channelRestrictions.high;
// Get country restrictions
auto channelRestrictions = m_wifi.getChannelRestrictions();
uint8_t lowCh = channelRestrictions.low;
uint8_t highCh = channelRestrictions.high;

SPSP_LOGI("Connect to bridge: channels %u - %u", lowCh, highCh);
SPSP_LOGI("Connect to bridge: channels %u - %u", lowCh, highCh);

// Clear previous results
m_bestBridge = {};
// Clear previous results
m_bestBridge = {};

// Prepare message
LocalMessageT msg = {};
msg.addr = LocalAddrT::broadcast();
msg.type = LocalMessageType::PROBE_REQ;
msg.payload = SPSP::VERSION;
// Prepare message
LocalMessageT msg = {};
msg.addr = LocalAddrT::broadcast();
msg.type = LocalMessageType::PROBE_REQ;
msg.payload = SPSP::VERSION;

// Convert to raw data
std::string data;
m_serdes.serialize(msg, data);
// Convert to raw data
std::string data;
m_serdes.serialize(msg, data);

// Promise/mutex bucket
auto bucketId = this->getBucketIdFromLocalAddr(msg.addr);
// Promise/mutex bucket
auto bucketId = this->getBucketIdFromLocalAddr(msg.addr);

// Probe all channels
for (uint8_t ch = lowCh; ch <= highCh; ch++) {
auto future = m_sendingPromises[bucketId].get_future();
// Probe all channels
for (uint8_t ch = lowCh; ch <= highCh; ch++) {
auto future = m_sendingPromises[bucketId].get_future();

m_wifi.setChannel(ch);
this->sendRaw(msg.addr, data);
m_wifi.setChannel(ch);
this->sendRaw(msg.addr, data);

SPSP_LOGD("Connect to bridge: waiting for callback");
SPSP_LOGD("Connect to bridge: waiting for callback");

// Wait for callback to finish
future.get();
// Wait for callback to finish
future.get();

// Reset promise
m_sendingPromises[bucketId] = std::promise<bool>{};
// Reset promise
m_sendingPromises[bucketId] = std::promise<bool>{};

// Sleep
std::this_thread::sleep_for(m_conf.connectToBridgeChannelWaiting);
}
// Sleep
std::this_thread::sleep_for(m_conf.connectToBridgeChannelWaiting);
}

// No response
if (m_bestBridge.empty()) {
SPSP_LOGE("Connect to bridge: no response from bridge");
return false;
}
// No response
if (m_bestBridge.empty()) {
SPSP_LOGE("Connect to bridge: no response from bridge");
return false;
}

// New best bridge is available - switch to it's channel
m_wifi.setChannel(m_bestBridge.ch);
// New best bridge is available - switch to it's channel
m_wifi.setChannel(m_bestBridge.ch);

SPSP_LOGI("Connected to bridge: %s on channel %u (%d dBm)",
m_bestBridge.addr.str.c_str(), m_bestBridge.ch,
m_bestBridge.rssi);
SPSP_LOGI("Connected to bridge: %s on channel %u (%d dBm)",
m_bestBridge.addr.str.c_str(), m_bestBridge.ch,
m_bestBridge.rssi);

if (connBr != nullptr) {
*connBr = m_bestBridge.toRTC();
if (connBr != nullptr) {
*connBr = m_bestBridge.toRTC();
}
} // Mutex

// Resubscribe to all topics
if (this->nodeConnected()) {
this->getNode()->resubscribeAll();
}

return true;
Expand Down

0 comments on commit 0a1d5cf

Please sign in to comment.