Merge branch 'master' into neighborinfo

This commit is contained in:
Ben Meadors
2023-06-19 06:16:42 -05:00
committed by GitHub
19 changed files with 341 additions and 148 deletions

View File

@@ -11,6 +11,7 @@
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "TypeConversions.h"
#include "error.h"
#include "main.h"
#include "mesh-pb-constants.h"
@@ -56,14 +57,18 @@ extern void getMacAddr(uint8_t *dmac);
* we use !macaddr (no colons).
*/
meshtastic_User &owner = devicestate.owner;
meshtastic_Position localPosition = meshtastic_Position_init_default;
meshtastic_CriticalErrorCode error_code =
meshtastic_CriticalErrorCode_NONE; // For the error code, only show values from this boot (discard value from flash)
uint32_t error_address = 0;
static uint8_t ourMacAddr[6];
NodeDB::NodeDB() : nodes(devicestate.node_db), numNodes(&devicestate.node_db_count) {}
NodeDB::NodeDB()
: 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
@@ -265,6 +270,9 @@ void NodeDB::resetNodes()
{
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
devicestate.node_db_lite_count = 0;
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
saveDeviceStateToDisk();
neighborInfoModule->resetNeighbors();
}
@@ -280,6 +288,7 @@ void NodeDB::installDefaultDeviceState()
devicestate.has_my_node = true;
devicestate.has_owner = true;
devicestate.node_db_count = 0;
devicestate.node_db_lite_count = 0;
devicestate.version = DEVICESTATE_CUR_VER;
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
@@ -319,10 +328,23 @@ void NodeDB::init()
owner.hw_model = HW_VENDOR;
// Include our owner in the node db under our nodenum
meshtastic_NodeInfo *info = getOrCreateNode(getNodeNum());
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getNodeNum());
info->user = owner;
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
Preferences preferences;
preferences.begin("meshtastic", false);
@@ -366,8 +388,8 @@ void NodeDB::pickNewNodeNum()
if (r == NODENUM_BROADCAST || r < NUM_RESERVED)
r = NUM_RESERVED; // don't pick a reserved node number
meshtastic_NodeInfo *found;
while ((found = getNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) {
meshtastic_NodeInfoLite *found;
while ((found = getMeshNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) {
NodeNum n = random(NUM_RESERVED, NODENUM_BROADCAST); // try a new random choice
LOG_DEBUG("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n);
r = n;
@@ -576,7 +598,7 @@ void NodeDB::saveToDisk(int saveWhat)
}
}
const meshtastic_NodeInfo *NodeDB::readNextInfo(uint32_t &readIndex)
const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex)
{
if (readIndex < *numNodes)
return &nodes[readIndex++];
@@ -584,8 +606,16 @@ const meshtastic_NodeInfo *NodeDB::readNextInfo(uint32_t &readIndex)
return NULL;
}
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
{
if (readIndex < *numMeshNodes)
return &meshNodes[readIndex++];
else
return NULL;
}
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
uint32_t sinceLastSeen(const meshtastic_NodeInfo *n)
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n)
{
uint32_t now = getTime();
@@ -609,13 +639,13 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
size_t NodeDB::getNumOnlineNodes()
size_t NodeDB::getNumOnlineMeshNodes()
{
size_t numseen = 0;
// FIXME this implementation is kinda expensive
for (int i = 0; i < *numNodes; i++)
if (sinceLastSeen(&nodes[i]) < NUM_ONLINE_SECS)
for (int i = 0; i < *numMeshNodes; i++)
if (sinceLastSeen(&meshNodes[i]) < NUM_ONLINE_SECS)
numseen++;
return numseen;
@@ -627,7 +657,7 @@ size_t NodeDB::getNumOnlineNodes()
*/
void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
if (!info) {
return;
}
@@ -636,7 +666,9 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
// Local packet, fully authoritative
LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
p.longitude_i, p.altitude);
info->position = p;
info->position = ConvertToPositionLite(p);
localPosition = p;
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
// (stop-gap fix for issue #900)
@@ -654,7 +686,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
uint32_t tmp_time = info->position.time;
// Next, update atomically
info->position = p;
info->position = ConvertToPositionLite(p);
// Last, restore any fields that may have been overwritten
if (!info->position.time)
@@ -670,7 +702,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
*/
void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
// Environment metrics should never go to NodeDb but we'll safegaurd anyway
if (!info || t.which_variant != meshtastic_Telemetry_device_metrics_tag) {
return;
@@ -692,7 +724,7 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
*/
bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
{
meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
if (!info) {
return false;
}
@@ -725,7 +757,7 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
LOG_DEBUG("Update DB node 0x%x, rx_time=%u, channel=%d\n", mp.from, mp.rx_time, mp.channel);
meshtastic_NodeInfo *info = getOrCreateNode(getFrom(&mp));
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp));
if (!info) {
return;
}
@@ -742,9 +774,9 @@ void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
}
}
uint8_t NodeDB::getNodeChannel(NodeNum n)
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
{
meshtastic_NodeInfo *info = getNode(n);
meshtastic_NodeInfoLite *info = getMeshNode(n);
if (!info) {
return 0; // defaults to PRIMARY
}
@@ -753,7 +785,7 @@ uint8_t NodeDB::getNodeChannel(NodeNum n)
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n)
{
for (int i = 0; i < *numNodes; i++)
if (nodes[i].num == n)
@@ -762,38 +794,100 @@ meshtastic_NodeInfo *NodeDB::getNode(NodeNum n)
return NULL;
}
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
{
meshtastic_NodeInfo *info = getNode(n);
for (int i = 0; i < *numMeshNodes; i++)
if (meshNodes[i].num == n)
return &meshNodes[i];
if (!info) {
if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) {
screen->print("warning: node_db full! erasing oldest entry\n");
return NULL;
}
/// Find a node in our DB, create an empty NodeInfo if missing
meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
{
meshtastic_NodeInfoLite *lite = getMeshNode(n);
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 < *numNodes; i++) {
if (nodes[i].last_heard < oldest) {
oldest = nodes[i].last_heard;
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 < *numNodes - 1; i++) {
nodes[i] = nodes[i + 1];
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
meshNodes[i] = meshNodes[i + 1];
}
(*numNodes)--;
(*numMeshNodes)--;
}
// add the node at the end
info = &nodes[(*numNodes)++];
lite = &meshNodes[(*numMeshNodes)++];
// everything is missing except the nodenum
memset(info, 0, sizeof(*info));
info->num = n;
memset(lite, 0, sizeof(*lite));
lite->num = n;
}
return info;
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