Merge branch 'master' into RGBLED

pull/3647/head
Gareth Coleman 2024-04-18 23:12:08 +01:00 zatwierdzone przez GitHub
commit 8ac308e73b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
2 zmienionych plików z 50 dodań i 121 usunięć

Wyświetl plik

@ -4,11 +4,8 @@
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h" #include "RTC.h"
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
NeighborInfoModule *neighborInfoModule; NeighborInfoModule *neighborInfoModule;
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
/* /*
Prints a single neighbor info packet and associated neighbors Prints a single neighbor info packet and associated neighbors
Uses LOG_DEBUG, which equates to Console.log Uses LOG_DEBUG, which equates to Console.log
@ -30,26 +27,23 @@ NOTE: for debugging only
*/ */
void NeighborInfoModule::printNodeDBNeighbors() void NeighborInfoModule::printNodeDBNeighbors()
{ {
int num_neighbors = getNumNeighbors(); LOG_DEBUG("Our NodeDB contains %d neighbors\n", neighbors.size());
LOG_DEBUG("Our NodeDB contains %d neighbors\n", num_neighbors); for (size_t i = 0; i < neighbors.size(); i++) {
for (int i = 0; i < num_neighbors; i++) { LOG_DEBUG("Node %d: node_id=0x%x, snr=%.2f\n", i, neighbors[i].node_id, neighbors[i].snr);
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
LOG_DEBUG(" Node %d: node_id=0x%x, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
} }
} }
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */ /* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
NeighborInfoModule::NeighborInfoModule() NeighborInfoModule::NeighborInfoModule()
: ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), : ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg),
concurrency::OSThread("NeighborInfoModule"), neighbors(neighborState.neighbors), concurrency::OSThread("NeighborInfoModule")
numNeighbors(&neighborState.neighbors_count)
{ {
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP; ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
if (moduleConfig.neighbor_info.enabled) { if (moduleConfig.neighbor_info.enabled) {
isPromiscuous = true; // Update neighbors from all packets isPromiscuous = true; // Update neighbors from all packets
this->loadProtoForModule(); setIntervalFromNow(
setIntervalFromNow(35 * 1000); Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs));
} else { } else {
LOG_DEBUG("NeighborInfoModule is disabled\n"); LOG_DEBUG("NeighborInfoModule is disabled\n");
disable(); disable();
@ -63,18 +57,17 @@ Assumes that the neighborInfo packet has been allocated
*/ */
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo) uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
{ {
uint my_node_id = nodeDB->getNodeNum(); NodeNum my_node_id = nodeDB->getNodeNum();
neighborInfo->node_id = my_node_id; neighborInfo->node_id = my_node_id;
neighborInfo->last_sent_by_id = my_node_id; neighborInfo->last_sent_by_id = my_node_id;
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
int num_neighbors = cleanUpNeighbors(); cleanUpNeighbors();
for (int i = 0; i < num_neighbors; i++) { for (auto nbr : neighbors) {
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i); if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (nbr.node_id != my_node_id)) {
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) { neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = nbr.node_id;
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id; neighborInfo->neighbors[neighborInfo->neighbors_count].snr = nbr.snr;
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr;
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over // Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over
// the mesh // the mesh
neighborInfo->neighbors_count++; neighborInfo->neighbors_count++;
@ -85,41 +78,22 @@ uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighb
} }
/* /*
Remove neighbors from the database that we haven't heard from in a while Remove neighbors from the database that we haven't heard from in a while
@returns new number of neighbors
*/ */
size_t NeighborInfoModule::cleanUpNeighbors() void NeighborInfoModule::cleanUpNeighbors()
{ {
uint32_t now = getTime(); uint32_t now = getTime();
int num_neighbors = getNumNeighbors();
NodeNum my_node_id = nodeDB->getNodeNum(); NodeNum my_node_id = nodeDB->getNodeNum();
for (auto it = neighbors.rbegin(); it != neighbors.rend();) {
// Find neighbors to remove
std::vector<int> indices_to_remove;
for (int i = 0; i < num_neighbors; i++) {
const meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval // We will remove a neighbor if we haven't heard from them in twice the broadcast interval
if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) { if ((now - it->last_rx_time > it->node_broadcast_interval_secs * 2) && (it->node_id != my_node_id)) {
indices_to_remove.push_back(i); LOG_DEBUG("Removing neighbor with node ID 0x%x\n", it->node_id);
it = std::vector<meshtastic_Neighbor>::reverse_iterator(
neighbors.erase(std::next(it).base())); // Erase the element and update the iterator
} else {
++it;
} }
} }
// Update the neighbor list
for (uint i = 0; i < indices_to_remove.size(); i++) {
int index = indices_to_remove[i];
LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id);
for (int j = index; j < num_neighbors - 1; j++) {
neighbors[j] = neighbors[j + 1];
}
(*numNeighbors)--;
}
// Save the neighbor list if we removed any neighbors or neighbors were already updated upon receiving a packet
if (indices_to_remove.size() > 0 || shouldSave) {
saveProtoForModule();
}
return *numNeighbors;
} }
/* Send neighbor info to the mesh */ /* Send neighbor info to the mesh */
@ -143,7 +117,9 @@ Will be used for broadcast.
int32_t NeighborInfoModule::runOnce() int32_t NeighborInfoModule::runOnce()
{ {
bool requestReplies = false; bool requestReplies = false;
sendNeighborInfo(NODENUM_BROADCAST, requestReplies); if (airTime->isTxAllowedChannelUtil(true) && airTime->isTxAllowedAirUtil()) {
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
}
return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs); return Default::getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs);
} }
@ -178,10 +154,7 @@ void NeighborInfoModule::alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtas
void NeighborInfoModule::resetNeighbors() void NeighborInfoModule::resetNeighbors()
{ {
*numNeighbors = 0; neighbors.clear();
neighborState.neighbors_count = 0;
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
saveProtoForModule();
} }
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np) void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np)
@ -201,61 +174,36 @@ meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSen
n = nodeDB->getNodeNum(); n = nodeDB->getNodeNum();
} }
// look for one in the existing list // look for one in the existing list
for (int i = 0; i < (*numNeighbors); i++) { for (size_t i = 0; i < neighbors.size(); i++) {
meshtastic_Neighbor *nbr = &neighbors[i]; if (neighbors[i].node_id == n) {
if (nbr->node_id == n) {
// if found, update it // if found, update it
nbr->snr = snr; neighbors[i].snr = snr;
nbr->last_rx_time = getTime(); neighbors[i].last_rx_time = getTime();
// Only if this is the original sender, the broadcast interval corresponds to it // Only if this is the original sender, the broadcast interval corresponds to it
if (originalSender == n && node_broadcast_interval_secs != 0) if (originalSender == n && node_broadcast_interval_secs != 0)
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; neighbors[i].node_broadcast_interval_secs = node_broadcast_interval_secs;
return nbr; return &neighbors[i];
} }
} }
// otherwise, allocate one and assign data to it // otherwise, allocate one and assign data to it
// TODO: max memory for the database should take neighbors into account, but currently doesn't
if (*numNeighbors < MAX_NUM_NEIGHBORS) { meshtastic_Neighbor new_nbr = meshtastic_Neighbor_init_zero;
(*numNeighbors)++; new_nbr.node_id = n;
} new_nbr.snr = snr;
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)]; new_nbr.last_rx_time = getTime();
new_nbr->node_id = n;
new_nbr->snr = snr;
new_nbr->last_rx_time = getTime();
// Only if this is the original sender, the broadcast interval corresponds to it // Only if this is the original sender, the broadcast interval corresponds to it
if (originalSender == n && node_broadcast_interval_secs != 0) if (originalSender == n && node_broadcast_interval_secs != 0)
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs; new_nbr.node_broadcast_interval_secs = node_broadcast_interval_secs;
else // Assume the same broadcast interval as us for the neighbor if we don't know it else // Assume the same broadcast interval as us for the neighbor if we don't know it
new_nbr->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval; new_nbr.node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
shouldSave = true; // Save the new neighbor upon next cleanup
return new_nbr;
}
void NeighborInfoModule::loadProtoForModule() if (neighbors.size() < MAX_NUM_NEIGHBORS) {
{ neighbors.push_back(new_nbr);
if (nodeDB->loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo), } else {
&meshtastic_NeighborInfo_msg, &neighborState) != LoadFileResult::SUCCESS) { // If we have too many neighbors, replace the oldest one
neighborState = meshtastic_NeighborInfo_init_zero; LOG_WARN("Neighbor DB is full, replacing oldest neighbor\n");
neighbors.erase(neighbors.begin());
neighbors.push_back(new_nbr);
} }
} return &neighbors.back();
/**
* @brief Save the module config to file.
*
* @return true On success.
* @return false On error.
*/
bool NeighborInfoModule::saveProtoForModule()
{
bool okay = true;
#ifdef FS
FS.mkdir("/prefs");
#endif
okay &= nodeDB->saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
if (okay)
shouldSave = false;
return okay;
} }

Wyświetl plik

@ -1,13 +1,13 @@
#pragma once #pragma once
#include "ProtobufModule.h" #include "ProtobufModule.h"
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
/* /*
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh * Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
*/ */
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
{ {
meshtastic_Neighbor *neighbors; std::vector<meshtastic_Neighbor> neighbors;
pb_size_t *numNeighbors;
public: public:
/* /*
@ -18,15 +18,7 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
/* Reset neighbor info after clearing nodeDB*/ /* Reset neighbor info after clearing nodeDB*/
void resetNeighbors(); void resetNeighbors();
bool saveProtoForModule();
private:
bool shouldSave = false; // Whether we should save the neighbor info to flash
protected: protected:
// Note: this holds our local info.
meshtastic_NeighborInfo neighborState;
/* /*
* Called to handle a particular incoming message * Called to handle a particular incoming message
* @return true if you've guaranteed you've handled this message and no other handlers should be considered for it * @return true if you've guaranteed you've handled this message and no other handlers should be considered for it
@ -40,10 +32,9 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo); uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
/* /*
Remove neighbors from the database that we haven't heard from in a while Remove neighbors from the database that we haven't heard from in a while
@returns new number of neighbors
*/ */
size_t cleanUpNeighbors(); void cleanUpNeighbors();
/* Allocate a new NeighborInfo packet */ /* Allocate a new NeighborInfo packet */
meshtastic_NeighborInfo *allocateNeighborInfoPacket(); meshtastic_NeighborInfo *allocateNeighborInfoPacket();
@ -56,22 +47,12 @@ class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, priva
*/ */
void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
size_t getNumNeighbors() { return *numNeighbors; }
meshtastic_Neighbor *getNeighborByIndex(size_t x)
{
assert(x < *numNeighbors);
return &neighbors[x];
}
/* update neighbors with subpacket sniffed from network */ /* update neighbors with subpacket sniffed from network */
void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np); void updateNeighbors(const meshtastic_MeshPacket &mp, const meshtastic_NeighborInfo *np);
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */ /* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override; void alterReceivedProtobuf(meshtastic_MeshPacket &p, meshtastic_NeighborInfo *n) override;
void loadProtoForModule();
/* Does our periodic broadcast */ /* Does our periodic broadcast */
int32_t runOnce() override; int32_t runOnce() override;