Broadcast neighbor info

also update trunk
This commit is contained in:
Thomas Göttgens 2023-05-31 13:18:09 +02:00
parent b1398d0770
commit 61661aed50
10 changed files with 390 additions and 8 deletions

View File

@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.9.1
version: 1.10.0
plugins:
sources:
- id: trunk
@ -10,7 +10,7 @@ lint:
enabled:
- taplo@0.7.0
- ruff@0.0.265
- yamllint@1.31.0
- yamllint@1.32.0
- isort@5.12.0
- markdownlint@0.34.0
- oxipng@8.0.0

View File

@ -14,6 +14,7 @@
#include "error.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "modules/NeighborInfoModule.h"
#include <ErriezCRC32.h>
#include <pb_decode.h>
#include <pb_encode.h>
@ -128,6 +129,8 @@ bool NodeDB::factoryReset()
installDefaultChannels();
// third, write everything to disk
saveToDisk();
// write NeighbourInfo
neighborInfoModule->saveProtoForModule();
#ifdef ARCH_ESP32
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
nvs_flash_erase();
@ -259,6 +262,7 @@ void NodeDB::resetNodes()
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
saveDeviceStateToDisk();
neighborInfoModule->resetNeighbors();
}
void NodeDB::installDefaultDeviceState()

View File

@ -227,7 +227,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
#define meshtastic_ChannelFile_size 638
#define meshtastic_DeviceState_size 22736
#define meshtastic_NodeRemoteHardwarePin_size 29
#define meshtastic_OEMStore_size 3142
#define meshtastic_OEMStore_size 3152
#ifdef __cplusplus
} /* extern "C" */

View File

@ -72,6 +72,9 @@ typedef struct _meshtastic_LocalModuleConfig {
/* The part of the config that is specific to the Remote Hardware module */
bool has_remote_hardware;
meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware;
/* The part of the config that is specific to the Neighbor Info module */
bool has_neighbor_info;
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
} meshtastic_LocalModuleConfig;
@ -81,9 +84,9 @@ extern "C" {
/* Initializer values for message structs */
#define meshtastic_LocalConfig_init_default {false, meshtastic_Config_DeviceConfig_init_default, false, meshtastic_Config_PositionConfig_init_default, false, meshtastic_Config_PowerConfig_init_default, false, meshtastic_Config_NetworkConfig_init_default, false, meshtastic_Config_DisplayConfig_init_default, false, meshtastic_Config_LoRaConfig_init_default, false, meshtastic_Config_BluetoothConfig_init_default, 0}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default}
#define meshtastic_LocalModuleConfig_init_default {false, meshtastic_ModuleConfig_MQTTConfig_init_default, false, meshtastic_ModuleConfig_SerialConfig_init_default, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_default, false, meshtastic_ModuleConfig_StoreForwardConfig_init_default, false, meshtastic_ModuleConfig_RangeTestConfig_init_default, false, meshtastic_ModuleConfig_TelemetryConfig_init_default, false, meshtastic_ModuleConfig_CannedMessageConfig_init_default, 0, false, meshtastic_ModuleConfig_AudioConfig_init_default, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_default, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_default}
#define meshtastic_LocalConfig_init_zero {false, meshtastic_Config_DeviceConfig_init_zero, false, meshtastic_Config_PositionConfig_init_zero, false, meshtastic_Config_PowerConfig_init_zero, false, meshtastic_Config_NetworkConfig_init_zero, false, meshtastic_Config_DisplayConfig_init_zero, false, meshtastic_Config_LoRaConfig_init_zero, false, meshtastic_Config_BluetoothConfig_init_zero, 0}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero}
#define meshtastic_LocalModuleConfig_init_zero {false, meshtastic_ModuleConfig_MQTTConfig_init_zero, false, meshtastic_ModuleConfig_SerialConfig_init_zero, false, meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero, false, meshtastic_ModuleConfig_StoreForwardConfig_init_zero, false, meshtastic_ModuleConfig_RangeTestConfig_init_zero, false, meshtastic_ModuleConfig_TelemetryConfig_init_zero, false, meshtastic_ModuleConfig_CannedMessageConfig_init_zero, 0, false, meshtastic_ModuleConfig_AudioConfig_init_zero, false, meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero, false, meshtastic_ModuleConfig_NeighborInfoConfig_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_LocalConfig_device_tag 1
@ -104,6 +107,7 @@ extern "C" {
#define meshtastic_LocalModuleConfig_version_tag 8
#define meshtastic_LocalModuleConfig_audio_tag 9
#define meshtastic_LocalModuleConfig_remote_hardware_tag 10
#define meshtastic_LocalModuleConfig_neighbor_info_tag 11
/* Struct field encoding specification for nanopb */
#define meshtastic_LocalConfig_FIELDLIST(X, a) \
@ -135,7 +139,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \
X(a, STATIC, SINGULAR, UINT32, version, 8) \
X(a, STATIC, OPTIONAL, MESSAGE, audio, 9) \
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10)
X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10) \
X(a, STATIC, OPTIONAL, MESSAGE, neighbor_info, 11)
#define meshtastic_LocalModuleConfig_CALLBACK NULL
#define meshtastic_LocalModuleConfig_DEFAULT NULL
#define meshtastic_LocalModuleConfig_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@ -147,6 +152,7 @@ X(a, STATIC, OPTIONAL, MESSAGE, remote_hardware, 10)
#define meshtastic_LocalModuleConfig_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig
#define meshtastic_LocalModuleConfig_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
#define meshtastic_LocalModuleConfig_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
#define meshtastic_LocalModuleConfig_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
extern const pb_msgdesc_t meshtastic_LocalConfig_msg;
extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
@ -157,7 +163,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 461
#define meshtastic_LocalModuleConfig_size 535
#define meshtastic_LocalModuleConfig_size 545
#ifdef __cplusplus
} /* extern "C" */

View File

@ -15,6 +15,9 @@ PB_BIND(meshtastic_ModuleConfig_MQTTConfig, meshtastic_ModuleConfig_MQTTConfig,
PB_BIND(meshtastic_ModuleConfig_RemoteHardwareConfig, meshtastic_ModuleConfig_RemoteHardwareConfig, AUTO)
PB_BIND(meshtastic_ModuleConfig_NeighborInfoConfig, meshtastic_ModuleConfig_NeighborInfoConfig, AUTO)
PB_BIND(meshtastic_ModuleConfig_AudioConfig, meshtastic_ModuleConfig_AudioConfig, AUTO)

View File

@ -114,6 +114,15 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
char root[16];
} meshtastic_ModuleConfig_MQTTConfig;
/* NeighborInfoModule Config */
typedef struct _meshtastic_ModuleConfig_NeighborInfoConfig {
/* Whether the Module is enabled */
bool enabled;
/* Interval in seconds of how often we should try to send our
Neighbor Info to the mesh */
uint32_t update_interval;
} meshtastic_ModuleConfig_NeighborInfoConfig;
/* Audio Config for codec2 voice */
typedef struct _meshtastic_ModuleConfig_AudioConfig {
/* Whether Audio is enabled */
@ -313,6 +322,8 @@ typedef struct _meshtastic_ModuleConfig {
meshtastic_ModuleConfig_AudioConfig audio;
/* TODO: REPLACE */
meshtastic_ModuleConfig_RemoteHardwareConfig remote_hardware;
/* TODO: REPLACE */
meshtastic_ModuleConfig_NeighborInfoConfig neighbor_info;
} payload_variant;
} meshtastic_ModuleConfig;
@ -345,6 +356,7 @@ extern "C" {
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
#define meshtastic_ModuleConfig_SerialConfig_baud_ENUMTYPE meshtastic_ModuleConfig_SerialConfig_Serial_Baud
@ -365,6 +377,7 @@ extern "C" {
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@ -376,6 +389,7 @@ extern "C" {
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0}
#define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
@ -394,6 +408,8 @@ extern "C" {
#define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
#define meshtastic_ModuleConfig_AudioConfig_bitrate_tag 3
@ -464,6 +480,7 @@ extern "C" {
#define meshtastic_ModuleConfig_canned_message_tag 7
#define meshtastic_ModuleConfig_audio_tag 8
#define meshtastic_ModuleConfig_remote_hardware_tag 9
#define meshtastic_ModuleConfig_neighbor_info_tag 10
/* Struct field encoding specification for nanopb */
#define meshtastic_ModuleConfig_FIELDLIST(X, a) \
@ -475,7 +492,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,range_test,payload_variant.r
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,telemetry,payload_variant.telemetry), 6) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,canned_message,payload_variant.canned_message), 7) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,audio,payload_variant.audio), 8) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9)
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_variant.remote_hardware), 9) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,neighbor_info,payload_variant.neighbor_info), 10)
#define meshtastic_ModuleConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_payload_variant_mqtt_MSGTYPE meshtastic_ModuleConfig_MQTTConfig
@ -487,6 +505,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,remote_hardware,payload_vari
#define meshtastic_ModuleConfig_payload_variant_canned_message_MSGTYPE meshtastic_ModuleConfig_CannedMessageConfig
#define meshtastic_ModuleConfig_payload_variant_audio_MSGTYPE meshtastic_ModuleConfig_AudioConfig
#define meshtastic_ModuleConfig_payload_variant_remote_hardware_MSGTYPE meshtastic_ModuleConfig_RemoteHardwareConfig
#define meshtastic_ModuleConfig_payload_variant_neighbor_info_MSGTYPE meshtastic_ModuleConfig_NeighborInfoConfig
#define meshtastic_ModuleConfig_MQTTConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
@ -508,6 +527,12 @@ X(a, STATIC, REPEATED, MESSAGE, available_pins, 3)
#define meshtastic_ModuleConfig_RemoteHardwareConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_RemoteHardwareConfig_available_pins_MSGTYPE meshtastic_RemoteHardwarePin
#define meshtastic_ModuleConfig_NeighborInfoConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, update_interval, 2)
#define meshtastic_ModuleConfig_NeighborInfoConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_NeighborInfoConfig_DEFAULT NULL
#define meshtastic_ModuleConfig_AudioConfig_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, BOOL, codec2_enabled, 1) \
X(a, STATIC, SINGULAR, UINT32, ptt_pin, 2) \
@ -601,6 +626,7 @@ X(a, STATIC, SINGULAR, UENUM, type, 3)
extern const pb_msgdesc_t meshtastic_ModuleConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_AudioConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_SerialConfig_msg;
extern const pb_msgdesc_t meshtastic_ModuleConfig_ExternalNotificationConfig_msg;
@ -614,6 +640,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_fields &meshtastic_ModuleConfig_msg
#define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
#define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg
#define meshtastic_ModuleConfig_AudioConfig_fields &meshtastic_ModuleConfig_AudioConfig_msg
#define meshtastic_ModuleConfig_SerialConfig_fields &meshtastic_ModuleConfig_SerialConfig_msg
#define meshtastic_ModuleConfig_ExternalNotificationConfig_fields &meshtastic_ModuleConfig_ExternalNotificationConfig_msg
@ -628,6 +655,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
#define meshtastic_ModuleConfig_MQTTConfig_size 220
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96
#define meshtastic_ModuleConfig_SerialConfig_size 28

View File

@ -5,6 +5,7 @@
#include "input/cardKbI2cImpl.h"
#include "modules/AdminModule.h"
#include "modules/CannedMessageModule.h"
#include "modules/NeighborInfoModule.h"
#include "modules/NodeInfoModule.h"
#include "modules/PositionModule.h"
#include "modules/RemoteHardwareModule.h"
@ -89,6 +90,7 @@ void setupModules()
} else {
adminModule = new AdminModule();
traceRouteModule = new TraceRouteModule();
neighborInfoModule = new NeighborInfoModule();
}
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
// acks

View File

@ -0,0 +1,249 @@
#include "NeighborInfoModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#define MAX_NEIGHBOR_AGE 10 * 60 * 1000 // 10 minutes
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
NeighborInfoModule *neighborInfoModule;
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
/*
Prints a single neighbor info packet and associated neighbors
Uses LOG_DEBUG, which equates to Console.log
NOTE: For debugging only
*/
void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np)
{
LOG_DEBUG("%s NEIGHBORINFO PACKET from Node %d to Node %d (last sent by %d)\n", header, np->node_id, nodeDB.getNodeNum(),
np->last_sent_by_id);
LOG_DEBUG("----------------\n");
LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count);
for (int i = 0; i < np->neighbors_count; i++) {
LOG_DEBUG("Neighbor %d: node_id=%d, snr=%d\n", i, np->neighbors[i].node_id, np->neighbors[i].snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB nodes so we can see whose nodeInfo we have
NOTE: for debugging only
*/
void NeighborInfoModule::printNodeDBNodes(const char *header)
{
int num_nodes = nodeDB.getNumNodes();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d nodes\n", num_nodes);
for (int i = 0; i < num_nodes; i++) {
meshtastic_NodeInfo *dbEntry = nodeDB.getNodeByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%d\n", i, dbEntry->num, dbEntry->snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB neighbors
NOTE: for debugging only
*/
void NeighborInfoModule::printNodeDBNeighbors(const char *header)
{
int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%d\n", i, dbEntry->node_id, dbEntry->snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB with selectors for the neighbors we've chosen to send (inefficiently)
Uses LOG_DEBUG, which equates to Console.log
NOTE: For debugging only
*/
void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np)
{
int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors);
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
bool chosen = false;
for (int j = 0; j < np->neighbors_count; j++) {
if (np->neighbors[j].node_id == dbEntry->node_id) {
chosen = true;
}
}
if (!chosen) {
LOG_DEBUG(" Node %d: neighbor=%d, snr=%d\n", i, dbEntry->node_id, dbEntry->snr);
} else {
LOG_DEBUG("---> Node %d: neighbor=%d, snr=%d\n", i, dbEntry->node_id, dbEntry->snr);
}
}
LOG_DEBUG("----------------\n");
}
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
NeighborInfoModule::NeighborInfoModule()
: neighbors(neighborState.neighbors), numNeighbors(&neighborState.neighbors_count),
ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), concurrency::OSThread(
"NeighborInfoModule")
{
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
if (moduleConfig.neighbor_info.enabled) {
this->loadProtoForModule();
setIntervalFromNow(35 * 1000);
} else {
LOG_DEBUG("NeighborInfoModule is disabled\n");
disable();
}
}
/*
Allocate a zeroed neighbor info packet
*/
meshtastic_NeighborInfo *NeighborInfoModule::allocateNeighborInfoPacket()
{
meshtastic_NeighborInfo *neighborInfo = (meshtastic_NeighborInfo *)malloc(sizeof(meshtastic_NeighborInfo));
memset(neighborInfo, 0, sizeof(meshtastic_NeighborInfo));
return neighborInfo;
}
/*
Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
Assumes that the neighborInfo packet has been allocated
@returns the number of entries collected
*/
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
{
int num_neighbors = getNumNeighbors();
int current_time = getTime();
int my_node_id = nodeDB.getNodeNum();
neighborInfo->node_id = my_node_id;
neighborInfo->last_sent_by_id = my_node_id;
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) {
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id;
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr;
neighborInfo->neighbors_count++;
}
}
printNodeDBNodes("DBSTATE");
printNodeDBNeighbors("NEIGHBORS");
printNodeDBSelection("COLLECTED", neighborInfo);
return neighborInfo->neighbors_count;
}
/* Send neighbor info to the mesh */
void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
{
meshtastic_NeighborInfo *neighborInfo = allocateNeighborInfoPacket();
collectNeighborInfo(neighborInfo);
meshtastic_MeshPacket *p = allocDataProtobuf(*neighborInfo);
// send regardless of whether or not we have neighbors in our DB,
// because we want to get neighbors for the next cycle
p->to = dest;
p->decoded.want_response = wantReplies;
printNeighborInfo("SENDING", neighborInfo);
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
/*
Encompasses the full construction and sending packet to mesh
Will be used for broadcast.
*/
int32_t NeighborInfoModule::runOnce()
{
bool requestReplies = false;
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
return getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs);
}
/*
Collect a recieved neighbor info packet from another node
Pass it to an upper client; do not persist this data on the mesh
*/
bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
{
printNeighborInfo("RECIEVED", np);
updateNeighbors(mp, np);
np->last_sent_by_id = nodeDB.getNodeNum();
// Allow others to handle this packet
return false;
}
void NeighborInfoModule::resetNeighbors()
{
neighborState.neighbors_count = 0;
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
saveProtoForModule();
}
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
{
// The last sent ID will be 0 if the packet is from the phone, which we don't count as
// an edge. So we assume that if it's zero, then this packet is from our node.
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
getOrCreateNeighbor(np->last_sent_by_id, mp.rx_snr);
}
}
meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum n, int snr)
{
// our node and the phone are the same node (not neighbors)
if (n == 0) {
n = nodeDB.getNodeNum();
}
// look for one in the existing list
for (int i = 0; i < (*numNeighbors); i++) {
meshtastic_Neighbor *nbr = &neighbors[i];
if (nbr->node_id == n) {
// if found, update it
nbr->snr = snr;
return nbr;
}
}
// 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_NODES) {
(*numNeighbors)++;
}
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];
new_nbr->node_id = n;
new_nbr->snr = snr;
return new_nbr;
}
void NeighborInfoModule::loadProtoForModule()
{
if (!nodeDB.loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
&meshtastic_NeighborInfo_msg, &neighborState)) {
neighborState = meshtastic_NeighborInfo_init_zero;
}
}
/**
* @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);
return okay;
}

View File

@ -0,0 +1,72 @@
#pragma once
#include "ProtobufModule.h"
/*
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
*/
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
{
meshtastic_Neighbor *neighbors;
pb_size_t *numNeighbors;
public:
/*
* Expose the constructor
*/
NeighborInfoModule();
/* Reset neighbor info after clearing nodeDB*/
void resetNeighbors();
bool saveProtoForModule();
protected:
// Note: this holds our local info.
meshtastic_NeighborInfo neighborState;
/*
* 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
*/
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override;
/*
* Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
* @return the number of entries collected
*/
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
/* Allocate a new NeighborInfo packet */
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
/// Find a neighbor in our DB, create an empty neighbor if missing
meshtastic_Neighbor *getOrCreateNeighbor(NodeNum n, int snr);
/*
* Send info on our node's neighbors into the mesh
*/
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 */
void updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np);
void loadProtoForModule();
/* Does our periodic broadcast */
int32_t runOnce() override;
/* These are for debugging only */
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
void printNodeDBNodes(const char *header);
void printNodeDBNeighbors(const char *header);
void printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np);
};
extern NeighborInfoModule *neighborInfoModule;

View File

@ -544,6 +544,24 @@ std::string MQTT::downstreamPacketToJson(meshtastic_MeshPacket *mp)
};
break;
}
case meshtastic_PortNum_NEIGHBORINFO_APP: {
msgType = "neighborinfo";
meshtastic_NeighborInfo scratch;
meshtastic_NeighborInfo *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_NeighborInfo_msg,
&scratch)) {
decoded = &scratch;
msgPayload["node_id"] = new JSONValue((int)decoded->node_id);
msgPayload["neighbors_count"] = new JSONValue((int)decoded->neighbors_count);
msgPayload["neighbors"] = new JSONValue(decoded->neighbors);
} else {
LOG_ERROR("Error decoding protobuf for neighborinfo message!\n");
}
};
break;
}
// add more packet types here if needed
default:
break;