mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-26 18:09:04 +00:00
Merge branch 'master' into picomputer-s3
This commit is contained in:
commit
e3260c1d19
@ -1,6 +1,6 @@
|
|||||||
version: 0.1
|
version: 0.1
|
||||||
cli:
|
cli:
|
||||||
version: 1.9.1
|
version: 1.10.0
|
||||||
plugins:
|
plugins:
|
||||||
sources:
|
sources:
|
||||||
- id: trunk
|
- id: trunk
|
||||||
@ -10,7 +10,7 @@ lint:
|
|||||||
enabled:
|
enabled:
|
||||||
- taplo@0.7.0
|
- taplo@0.7.0
|
||||||
- ruff@0.0.265
|
- ruff@0.0.265
|
||||||
- yamllint@1.31.0
|
- yamllint@1.32.0
|
||||||
- isort@5.12.0
|
- isort@5.12.0
|
||||||
- markdownlint@0.34.0
|
- markdownlint@0.34.0
|
||||||
- oxipng@8.0.0
|
- oxipng@8.0.0
|
||||||
|
@ -49,10 +49,13 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
|
|||||||
|
|
||||||
tosend->hop_limit--; // bump down the hop count
|
tosend->hop_limit--; // bump down the hop count
|
||||||
|
|
||||||
// If it is a traceRoute request, update the route that it went via me
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule &&
|
// If it is a traceRoute request, update the route that it went via me
|
||||||
traceRouteModule->wantPacket(p)) {
|
if (traceRouteModule && traceRouteModule->wantPacket(p))
|
||||||
traceRouteModule->updateRoute(tosend);
|
traceRouteModule->updateRoute(tosend);
|
||||||
|
// If it is a neighborInfo packet, update last_sent_by_id
|
||||||
|
if (neighborInfoModule && neighborInfoModule->wantPacket(p))
|
||||||
|
neighborInfoModule->updateLastSentById(tosend);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
|
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "PacketHistory.h"
|
#include "PacketHistory.h"
|
||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include "modules/TraceRouteModule.h"
|
#include "modules/TraceRouteModule.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include <ErriezCRC32.h>
|
#include <ErriezCRC32.h>
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
@ -63,11 +64,7 @@ uint32_t error_address = 0;
|
|||||||
|
|
||||||
static uint8_t ourMacAddr[6];
|
static uint8_t ourMacAddr[6];
|
||||||
|
|
||||||
NodeDB::NodeDB()
|
NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestate.node_db_lite_count) {}
|
||||||
: nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite),
|
|
||||||
numMeshNodes(&devicestate.node_db_lite_count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
|
||||||
@ -248,6 +245,9 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
|
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
|
||||||
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
|
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
|
||||||
|
|
||||||
|
moduleConfig.has_neighbor_info = true;
|
||||||
|
moduleConfig.neighbor_info.enabled = false;
|
||||||
|
|
||||||
initModuleConfigIntervals();
|
initModuleConfigIntervals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +271,7 @@ void NodeDB::initModuleConfigIntervals()
|
|||||||
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
|
||||||
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
|
||||||
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
|
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
|
||||||
|
moduleConfig.neighbor_info.update_interval = default_broadcast_interval_secs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultChannels()
|
void NodeDB::installDefaultChannels()
|
||||||
@ -282,12 +283,11 @@ void NodeDB::installDefaultChannels()
|
|||||||
|
|
||||||
void NodeDB::resetNodes()
|
void NodeDB::resetNodes()
|
||||||
{
|
{
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
|
|
||||||
|
|
||||||
devicestate.node_db_lite_count = 0;
|
devicestate.node_db_lite_count = 0;
|
||||||
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
|
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
|
||||||
saveDeviceStateToDisk();
|
saveDeviceStateToDisk();
|
||||||
|
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
||||||
|
neighborInfoModule->resetNeighbors();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::installDefaultDeviceState()
|
void NodeDB::installDefaultDeviceState()
|
||||||
@ -295,12 +295,11 @@ void NodeDB::installDefaultDeviceState()
|
|||||||
LOG_INFO("Installing default DeviceState\n");
|
LOG_INFO("Installing default DeviceState\n");
|
||||||
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
|
||||||
|
|
||||||
*numNodes = 0;
|
*numMeshNodes = 0;
|
||||||
|
|
||||||
// init our devicestate with valid flags so protobuf writing/reading will work
|
// init our devicestate with valid flags so protobuf writing/reading will work
|
||||||
devicestate.has_my_node = true;
|
devicestate.has_my_node = true;
|
||||||
devicestate.has_owner = true;
|
devicestate.has_owner = true;
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
devicestate.node_db_lite_count = 0;
|
devicestate.node_db_lite_count = 0;
|
||||||
devicestate.version = DEVICESTATE_CUR_VER;
|
devicestate.version = DEVICESTATE_CUR_VER;
|
||||||
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
|
||||||
@ -328,11 +327,9 @@ void NodeDB::init()
|
|||||||
int saveWhat = 0;
|
int saveWhat = 0;
|
||||||
|
|
||||||
// likewise - we always want the app requirements to come from the running appload
|
// likewise - we always want the app requirements to come from the running appload
|
||||||
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
|
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
|
||||||
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
|
|
||||||
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
|
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
|
||||||
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
|
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
|
||||||
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
|
|
||||||
pickNewNodeNum();
|
pickNewNodeNum();
|
||||||
|
|
||||||
// Set our board type so we can share it with others
|
// Set our board type so we can share it with others
|
||||||
@ -343,19 +340,6 @@ void NodeDB::init()
|
|||||||
info->user = owner;
|
info->user = owner;
|
||||||
info->has_user = true;
|
info->has_user = true;
|
||||||
|
|
||||||
if (*numNodes > 0) {
|
|
||||||
LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n");
|
|
||||||
uint32_t readIndex = 0;
|
|
||||||
const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
|
|
||||||
while (oldNodeInfo != NULL) {
|
|
||||||
migrateToNodeInfoLite(oldNodeInfo);
|
|
||||||
oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
|
|
||||||
}
|
|
||||||
LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n");
|
|
||||||
devicestate.node_db_count = 0;
|
|
||||||
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
preferences.begin("meshtastic", false);
|
preferences.begin("meshtastic", false);
|
||||||
@ -365,7 +349,7 @@ void NodeDB::init()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numMeshNodes);
|
||||||
|
|
||||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||||
saveWhat |= SEGMENT_DEVICESTATE;
|
saveWhat |= SEGMENT_DEVICESTATE;
|
||||||
@ -611,14 +595,6 @@ void NodeDB::saveToDisk(int saveWhat)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex)
|
|
||||||
{
|
|
||||||
if (readIndex < *numNodes)
|
|
||||||
return &nodes[readIndex++];
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
||||||
{
|
{
|
||||||
if (readIndex < *numMeshNodes)
|
if (readIndex < *numMeshNodes)
|
||||||
@ -796,17 +772,6 @@ uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
|||||||
return info->channel;
|
return info->channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find a node in our DB, return null for missing
|
|
||||||
/// NOTE: This function might be called from an ISR
|
|
||||||
meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < *numNodes; i++)
|
|
||||||
if (nodes[i].num == n)
|
|
||||||
return &nodes[i];
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a node in our DB, return null for missing
|
/// Find a node in our DB, return null for missing
|
||||||
/// NOTE: This function might be called from an ISR
|
/// NOTE: This function might be called from an ISR
|
||||||
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
|
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
|
||||||
@ -852,57 +817,6 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
|||||||
return lite;
|
return lite;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node)
|
|
||||||
{
|
|
||||||
meshtastic_NodeInfoLite *lite = getMeshNode(node->num);
|
|
||||||
|
|
||||||
if (!lite) {
|
|
||||||
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
|
|
||||||
screen->print("warning: node_db_lite full! erasing oldest entry\n");
|
|
||||||
// look for oldest node and erase it
|
|
||||||
uint32_t oldest = UINT32_MAX;
|
|
||||||
int oldestIndex = -1;
|
|
||||||
for (int i = 0; i < *numMeshNodes; i++) {
|
|
||||||
if (meshNodes[i].last_heard < oldest) {
|
|
||||||
oldest = meshNodes[i].last_heard;
|
|
||||||
oldestIndex = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Shove the remaining nodes down the chain
|
|
||||||
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
|
|
||||||
meshNodes[i] = meshNodes[i + 1];
|
|
||||||
}
|
|
||||||
(*numMeshNodes)--;
|
|
||||||
}
|
|
||||||
// add the node at the end
|
|
||||||
lite = &meshNodes[(*numMeshNodes)++];
|
|
||||||
|
|
||||||
// everything is missing except the nodenum
|
|
||||||
memset(lite, 0, sizeof(*lite));
|
|
||||||
lite->num = node->num;
|
|
||||||
lite->snr = node->snr;
|
|
||||||
lite->last_heard = node->last_heard;
|
|
||||||
lite->channel = node->channel;
|
|
||||||
|
|
||||||
if (node->has_position) {
|
|
||||||
lite->has_position = true;
|
|
||||||
lite->position.latitude_i = node->position.latitude_i;
|
|
||||||
lite->position.longitude_i = node->position.longitude_i;
|
|
||||||
lite->position.altitude = node->position.altitude;
|
|
||||||
lite->position.location_source = node->position.location_source;
|
|
||||||
lite->position.time = node->position.time;
|
|
||||||
}
|
|
||||||
if (node->has_user) {
|
|
||||||
lite->has_user = true;
|
|
||||||
lite->user = node->user;
|
|
||||||
}
|
|
||||||
if (node->has_device_metrics) {
|
|
||||||
lite->has_device_metrics = true;
|
|
||||||
lite->device_metrics = node->device_metrics;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Record an error that should be reported via analytics
|
/// Record an error that should be reported via analytics
|
||||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ DeviceState versions used to be defined in the .proto file but really only this
|
|||||||
#define SEGMENT_DEVICESTATE 4
|
#define SEGMENT_DEVICESTATE 4
|
||||||
#define SEGMENT_CHANNELS 8
|
#define SEGMENT_CHANNELS 8
|
||||||
|
|
||||||
#define DEVICESTATE_CUR_VER 20
|
#define DEVICESTATE_CUR_VER 22
|
||||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||||
|
|
||||||
extern meshtastic_DeviceState devicestate;
|
extern meshtastic_DeviceState devicestate;
|
||||||
@ -45,9 +45,6 @@ class NodeDB
|
|||||||
// Eventually use a smarter datastructure
|
// Eventually use a smarter datastructure
|
||||||
// HashMap<NodeNum, NodeInfo> nodes;
|
// HashMap<NodeNum, NodeInfo> nodes;
|
||||||
// Note: these two references just point into our static array we serialize to/from disk
|
// Note: these two references just point into our static array we serialize to/from disk
|
||||||
meshtastic_NodeInfo *nodes;
|
|
||||||
pb_size_t *numNodes;
|
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *meshNodes;
|
meshtastic_NodeInfoLite *meshNodes;
|
||||||
pb_size_t *numMeshNodes;
|
pb_size_t *numMeshNodes;
|
||||||
|
|
||||||
@ -137,18 +134,6 @@ class NodeDB
|
|||||||
private:
|
private:
|
||||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||||
void migrateToNodeInfoLite(const meshtastic_NodeInfo *node);
|
|
||||||
/// Find a node in our DB, return null for missing
|
|
||||||
meshtastic_NodeInfo *getNodeInfo(NodeNum n);
|
|
||||||
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
|
|
||||||
const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex);
|
|
||||||
size_t getNumNodes() { return *numNodes; }
|
|
||||||
|
|
||||||
meshtastic_NodeInfo *getNodeByIndex(size_t x)
|
|
||||||
{
|
|
||||||
assert(x < *numNodes);
|
|
||||||
return &nodes[x];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Notify observers of changes to the DB
|
/// Notify observers of changes to the DB
|
||||||
void notifyObservers(bool forceUpdate = false)
|
void notifyObservers(bool forceUpdate = false)
|
||||||
@ -226,10 +211,6 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
|
|||||||
|
|
||||||
/// Sometimes we will have Position objects that only have a time, so check for
|
/// Sometimes we will have Position objects that only have a time, so check for
|
||||||
/// valid lat/lon
|
/// valid lat/lon
|
||||||
static inline bool hasValidPosition(const meshtastic_NodeInfo *n)
|
|
||||||
{
|
|
||||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
|
||||||
}
|
|
||||||
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
|
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
|
||||||
{
|
{
|
||||||
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
||||||
|
@ -279,6 +279,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
|||||||
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_ModuleConfig_neighbor_info_tag:
|
||||||
|
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
|
||||||
|
fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unknown module config type %d\n", config_state);
|
LOG_ERROR("Unknown module config type %d\n", config_state);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#define MAX_RX_TOPHONE 32
|
#define MAX_RX_TOPHONE 32
|
||||||
|
|
||||||
/// max number of nodes allowed in the mesh
|
/// max number of nodes allowed in the mesh
|
||||||
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db) / member_size(meshtastic_DeviceState, node_db[0]))
|
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db_lite) / member_size(meshtastic_DeviceState, node_db_lite[0]))
|
||||||
|
|
||||||
/// Max number of channels allowed
|
/// Max number of channels allowed
|
||||||
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))
|
||||||
|
@ -368,6 +368,11 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
|||||||
moduleConfig.has_remote_hardware = true;
|
moduleConfig.has_remote_hardware = true;
|
||||||
moduleConfig.remote_hardware = c.payload_variant.remote_hardware;
|
moduleConfig.remote_hardware = c.payload_variant.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_ModuleConfig_neighbor_info_tag:
|
||||||
|
LOG_INFO("Setting module config: Neighbor Info\n");
|
||||||
|
moduleConfig.has_neighbor_info = true;
|
||||||
|
moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveChanges(SEGMENT_MODULECONFIG);
|
saveChanges(SEGMENT_MODULECONFIG);
|
||||||
@ -503,6 +508,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
|
||||||
res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware;
|
||||||
break;
|
break;
|
||||||
|
case meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG:
|
||||||
|
LOG_INFO("Getting module config: Neighbor Info\n");
|
||||||
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
|
||||||
|
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "input/kbMatrixImpl.h"
|
#include "input/kbMatrixImpl.h"
|
||||||
#include "modules/AdminModule.h"
|
#include "modules/AdminModule.h"
|
||||||
#include "modules/CannedMessageModule.h"
|
#include "modules/CannedMessageModule.h"
|
||||||
|
#include "modules/NeighborInfoModule.h"
|
||||||
#include "modules/NodeInfoModule.h"
|
#include "modules/NodeInfoModule.h"
|
||||||
#include "modules/PositionModule.h"
|
#include "modules/PositionModule.h"
|
||||||
#include "modules/RemoteHardwareModule.h"
|
#include "modules/RemoteHardwareModule.h"
|
||||||
@ -48,6 +49,7 @@ void setupModules()
|
|||||||
waypointModule = new WaypointModule();
|
waypointModule = new WaypointModule();
|
||||||
textMessageModule = new TextMessageModule();
|
textMessageModule = new TextMessageModule();
|
||||||
traceRouteModule = new TraceRouteModule();
|
traceRouteModule = new TraceRouteModule();
|
||||||
|
neighborInfoModule = new NeighborInfoModule();
|
||||||
|
|
||||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||||
// to a global variable.
|
// to a global variable.
|
||||||
|
319
src/modules/NeighborInfoModule.cpp
Normal file
319
src/modules/NeighborInfoModule.cpp
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
#include "NeighborInfoModule.h"
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "NodeDB.h"
|
||||||
|
#include "RTC.h"
|
||||||
|
|
||||||
|
#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=%.2f\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.getNumMeshNodes();
|
||||||
|
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_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
|
||||||
|
LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\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=%.2f\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=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("---> Node %d: neighbor=%d, snr=%.2f\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 my_node_id = nodeDB.getNodeNum();
|
||||||
|
neighborInfo->node_id = my_node_id;
|
||||||
|
neighborInfo->last_sent_by_id = my_node_id;
|
||||||
|
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
|
||||||
|
|
||||||
|
int num_neighbors = cleanUpNeighbors();
|
||||||
|
|
||||||
|
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;
|
||||||
|
// 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
|
||||||
|
neighborInfo->neighbors_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printNodeDBNodes("DBSTATE");
|
||||||
|
printNodeDBNeighbors("NEIGHBORS");
|
||||||
|
printNodeDBSelection("COLLECTED", neighborInfo);
|
||||||
|
return neighborInfo->neighbors_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
|
@returns new number of neighbors
|
||||||
|
*/
|
||||||
|
size_t NeighborInfoModule::cleanUpNeighbors()
|
||||||
|
{
|
||||||
|
uint32_t now = getTime();
|
||||||
|
int num_neighbors = getNumNeighbors();
|
||||||
|
NodeNum my_node_id = nodeDB.getNodeNum();
|
||||||
|
|
||||||
|
// Find neighbors to remove
|
||||||
|
std::vector<int> indices_to_remove;
|
||||||
|
for (int i = 0; i < num_neighbors; i++) {
|
||||||
|
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
|
||||||
|
// 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)) {
|
||||||
|
indices_to_remove.push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the neighbor list
|
||||||
|
for (int 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
|
||||||
|
if (indices_to_remove.size() > 0) {
|
||||||
|
saveProtoForModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *numNeighbors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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("RECEIVED", np);
|
||||||
|
updateNeighbors(mp, np);
|
||||||
|
// Allow others to handle this packet
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum
|
||||||
|
*/
|
||||||
|
void NeighborInfoModule::updateLastSentById(meshtastic_MeshPacket *p)
|
||||||
|
{
|
||||||
|
auto &incoming = p->decoded;
|
||||||
|
meshtastic_NeighborInfo scratch;
|
||||||
|
meshtastic_NeighborInfo *updated = NULL;
|
||||||
|
memset(&scratch, 0, sizeof(scratch));
|
||||||
|
pb_decode_from_bytes(incoming.payload.bytes, incoming.payload.size, &meshtastic_NeighborInfo_msg, &scratch);
|
||||||
|
updated = &scratch;
|
||||||
|
|
||||||
|
updated->last_sent_by_id = nodeDB.getNodeNum();
|
||||||
|
|
||||||
|
// Set updated last_sent_by_id to the payload of the to be flooded packet
|
||||||
|
p->decoded.payload.size =
|
||||||
|
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_NeighborInfo_msg, updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeighborInfoModule::resetNeighbors()
|
||||||
|
{
|
||||||
|
*numNeighbors = 0;
|
||||||
|
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(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n,
|
||||||
|
uint32_t node_broadcast_interval_secs, 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;
|
||||||
|
nbr->last_rx_time = getTime();
|
||||||
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
|
if (originalSender == n)
|
||||||
|
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
|
saveProtoForModule(); // Save the updated neighbor
|
||||||
|
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;
|
||||||
|
new_nbr->last_rx_time = getTime();
|
||||||
|
// Only if this is the original sender, the broadcast interval corresponds to it
|
||||||
|
if (originalSender == n)
|
||||||
|
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
|
||||||
|
saveProtoForModule(); // Save the new neighbor
|
||||||
|
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;
|
||||||
|
}
|
84
src/modules/NeighborInfoModule.h
Normal file
84
src/modules/NeighborInfoModule.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#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();
|
||||||
|
|
||||||
|
// Let FloodingRouter call updateLastSentById upon rebroadcasting a NeighborInfo packet
|
||||||
|
friend class FloodingRouter;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove neighbors from the database that we haven't heard from in a while
|
||||||
|
@returns new number of neighbors
|
||||||
|
*/
|
||||||
|
size_t cleanUpNeighbors();
|
||||||
|
|
||||||
|
/* Allocate a new NeighborInfo packet */
|
||||||
|
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
|
||||||
|
|
||||||
|
// Find a neighbor in our DB, create an empty neighbor if missing
|
||||||
|
meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, 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);
|
||||||
|
|
||||||
|
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
|
||||||
|
void updateLastSentById(meshtastic_MeshPacket *p);
|
||||||
|
|
||||||
|
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;
|
@ -363,6 +363,19 @@ JSONValue::JSONValue(int m_integer_value)
|
|||||||
number_value = (double)m_integer_value;
|
number_value = (double)m_integer_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic constructor for creating a JSON Value of type Number
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*
|
||||||
|
* @param uint m_integer_value The number to use as the value
|
||||||
|
*/
|
||||||
|
JSONValue::JSONValue(uint m_integer_value)
|
||||||
|
{
|
||||||
|
type = JSONType_Number;
|
||||||
|
number_value = (double)m_integer_value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic constructor for creating a JSON Value of type Array
|
* Basic constructor for creating a JSON Value of type Array
|
||||||
*
|
*
|
||||||
|
@ -45,6 +45,7 @@ class JSONValue
|
|||||||
JSONValue(bool m_bool_value);
|
JSONValue(bool m_bool_value);
|
||||||
JSONValue(double m_number_value);
|
JSONValue(double m_number_value);
|
||||||
JSONValue(int m_integer_value);
|
JSONValue(int m_integer_value);
|
||||||
|
JSONValue(uint m_integer_value);
|
||||||
JSONValue(const JSONArray &m_array_value);
|
JSONValue(const JSONArray &m_array_value);
|
||||||
JSONValue(const JSONObject &m_object_value);
|
JSONValue(const JSONObject &m_object_value);
|
||||||
JSONValue(const JSONValue &m_source);
|
JSONValue(const JSONValue &m_source);
|
||||||
|
@ -541,7 +541,7 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
|||||||
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) {
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) {
|
||||||
decoded = &scratch;
|
decoded = &scratch;
|
||||||
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
||||||
msgPayload["battery_level"] = new JSONValue((int)decoded->variant.device_metrics.battery_level);
|
msgPayload["battery_level"] = new JSONValue((uint)decoded->variant.device_metrics.battery_level);
|
||||||
msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage);
|
msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage);
|
||||||
msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization);
|
msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization);
|
||||||
msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx);
|
msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx);
|
||||||
@ -588,10 +588,10 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
|||||||
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) {
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) {
|
||||||
decoded = &scratch;
|
decoded = &scratch;
|
||||||
if ((int)decoded->time) {
|
if ((int)decoded->time) {
|
||||||
msgPayload["time"] = new JSONValue((int)decoded->time);
|
msgPayload["time"] = new JSONValue((uint)decoded->time);
|
||||||
}
|
}
|
||||||
if ((int)decoded->timestamp) {
|
if ((int)decoded->timestamp) {
|
||||||
msgPayload["timestamp"] = new JSONValue((int)decoded->timestamp);
|
msgPayload["timestamp"] = new JSONValue((uint)decoded->timestamp);
|
||||||
}
|
}
|
||||||
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
|
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
|
||||||
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
|
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
|
||||||
@ -599,13 +599,13 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
|||||||
msgPayload["altitude"] = new JSONValue((int)decoded->altitude);
|
msgPayload["altitude"] = new JSONValue((int)decoded->altitude);
|
||||||
}
|
}
|
||||||
if ((int)decoded->ground_speed) {
|
if ((int)decoded->ground_speed) {
|
||||||
msgPayload["ground_speed"] = new JSONValue((int)decoded->ground_speed);
|
msgPayload["ground_speed"] = new JSONValue((uint)decoded->ground_speed);
|
||||||
}
|
}
|
||||||
if (int(decoded->ground_track)) {
|
if (int(decoded->ground_track)) {
|
||||||
msgPayload["ground_track"] = new JSONValue((int)decoded->ground_track);
|
msgPayload["ground_track"] = new JSONValue((uint)decoded->ground_track);
|
||||||
}
|
}
|
||||||
if (int(decoded->sats_in_view)) {
|
if (int(decoded->sats_in_view)) {
|
||||||
msgPayload["sats_in_view"] = new JSONValue((int)decoded->sats_in_view);
|
msgPayload["sats_in_view"] = new JSONValue((uint)decoded->sats_in_view);
|
||||||
}
|
}
|
||||||
if ((int)decoded->PDOP) {
|
if ((int)decoded->PDOP) {
|
||||||
msgPayload["PDOP"] = new JSONValue((int)decoded->PDOP);
|
msgPayload["PDOP"] = new JSONValue((int)decoded->PDOP);
|
||||||
@ -632,11 +632,11 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
|||||||
memset(&scratch, 0, sizeof(scratch));
|
memset(&scratch, 0, sizeof(scratch));
|
||||||
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
|
||||||
decoded = &scratch;
|
decoded = &scratch;
|
||||||
msgPayload["id"] = new JSONValue((int)decoded->id);
|
msgPayload["id"] = new JSONValue((uint)decoded->id);
|
||||||
msgPayload["name"] = new JSONValue(decoded->name);
|
msgPayload["name"] = new JSONValue(decoded->name);
|
||||||
msgPayload["description"] = new JSONValue(decoded->description);
|
msgPayload["description"] = new JSONValue(decoded->description);
|
||||||
msgPayload["expire"] = new JSONValue((int)decoded->expire);
|
msgPayload["expire"] = new JSONValue((uint)decoded->expire);
|
||||||
msgPayload["locked_to"] = new JSONValue((int)decoded->locked_to);
|
msgPayload["locked_to"] = new JSONValue((uint)decoded->locked_to);
|
||||||
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
|
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
|
||||||
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
|
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
|
||||||
jsonObj["payload"] = new JSONValue(msgPayload);
|
jsonObj["payload"] = new JSONValue(msgPayload);
|
||||||
@ -646,16 +646,34 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
|||||||
};
|
};
|
||||||
break;
|
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((uint)decoded->node_id);
|
||||||
|
msgPayload["neighbors_count"] = new JSONValue(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
|
// add more packet types here if needed
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonObj["id"] = new JSONValue((int)mp->id);
|
jsonObj["id"] = new JSONValue((uint)mp->id);
|
||||||
jsonObj["timestamp"] = new JSONValue((int)mp->rx_time);
|
jsonObj["timestamp"] = new JSONValue((uint)mp->rx_time);
|
||||||
jsonObj["to"] = new JSONValue((int)mp->to);
|
jsonObj["to"] = new JSONValue((uint)mp->to);
|
||||||
jsonObj["from"] = new JSONValue((int)mp->from);
|
jsonObj["from"] = new JSONValue((uint)mp->from);
|
||||||
jsonObj["channel"] = new JSONValue((int)mp->channel);
|
jsonObj["channel"] = new JSONValue((uint)mp->channel);
|
||||||
jsonObj["type"] = new JSONValue(msgType.c_str());
|
jsonObj["type"] = new JSONValue(msgType.c_str());
|
||||||
jsonObj["sender"] = new JSONValue(owner.id);
|
jsonObj["sender"] = new JSONValue(owner.id);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user