mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-16 15:52:34 +00:00
Compare commits
5 Commits
refactor-n
...
esp32-h2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f0e704f29 | ||
|
|
23aaee737a | ||
|
|
42c46cad41 | ||
|
|
f0b72a4b4b | ||
|
|
24ca4602b1 |
@@ -10,10 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "FSCommon.h"
|
#include "FSCommon.h"
|
||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
#include "SafeFile.h"
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <pb_decode.h>
|
|
||||||
#include <pb_encode.h>
|
|
||||||
|
|
||||||
// Software SPI is used by MUI so disable SD card here until it's also implemented
|
// Software SPI is used by MUI so disable SD card here until it's also implemented
|
||||||
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
|
||||||
@@ -338,63 +335,4 @@ void setupSDCard()
|
|||||||
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
LOG_DEBUG("Total space: %lu MB", (uint32_t)(SD.totalBytes() / (1024 * 1024)));
|
||||||
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
LOG_DEBUG("Used space: %lu MB", (uint32_t)(SD.usedBytes() / (1024 * 1024)));
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
/** Load a protobuf from a file, return LoadFileResult */
|
|
||||||
LoadFileResult loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
|
||||||
{
|
|
||||||
LoadFileResult state = LoadFileResult::OTHER_FAILURE;
|
|
||||||
#ifdef FSCom
|
|
||||||
concurrency::LockGuard g(spiLock);
|
|
||||||
|
|
||||||
auto f = FSCom.open(filename, FILE_O_READ);
|
|
||||||
|
|
||||||
if (f) {
|
|
||||||
LOG_INFO("Load %s", filename);
|
|
||||||
pb_istream_t stream = {&readcb, &f, protoSize};
|
|
||||||
if (fields != &meshtastic_NodeDatabase_msg) // contains a vector object
|
|
||||||
memset(dest_struct, 0, objSize);
|
|
||||||
if (!pb_decode(&stream, fields, dest_struct)) {
|
|
||||||
LOG_ERROR("Error: can't decode protobuf %s", PB_GET_ERROR(&stream));
|
|
||||||
state = LoadFileResult::DECODE_FAILED;
|
|
||||||
} else {
|
|
||||||
LOG_INFO("Loaded %s successfully", filename);
|
|
||||||
state = LoadFileResult::LOAD_SUCCESS;
|
|
||||||
}
|
|
||||||
f.close();
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Could not open / read %s", filename);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
LOG_ERROR("ERROR: Filesystem not implemented");
|
|
||||||
state = LoadFileResult::NO_FILESYSTEM;
|
|
||||||
#endif
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Save a protobuf from a file, return true for success */
|
|
||||||
bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct, bool fullAtomic)
|
|
||||||
{
|
|
||||||
bool okay = false;
|
|
||||||
#ifdef FSCom
|
|
||||||
auto f = SafeFile(filename, fullAtomic);
|
|
||||||
|
|
||||||
LOG_INFO("Save %s", filename);
|
|
||||||
pb_ostream_t stream = {&writecb, static_cast<Print *>(&f), protoSize};
|
|
||||||
|
|
||||||
if (!pb_encode(&stream, fields, dest_struct)) {
|
|
||||||
LOG_ERROR("Error: can't encode protobuf %s", PB_GET_ERROR(&stream));
|
|
||||||
} else {
|
|
||||||
okay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool writeSucceeded = f.close();
|
|
||||||
|
|
||||||
if (!okay || !writeSucceeded) {
|
|
||||||
LOG_ERROR("Can't write prefs!");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
LOG_ERROR("ERROR: Filesystem not implemented");
|
|
||||||
#endif
|
|
||||||
return okay;
|
|
||||||
}
|
}
|
||||||
@@ -3,19 +3,6 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
enum LoadFileResult {
|
|
||||||
// Successfully opened the file
|
|
||||||
LOAD_SUCCESS = 1,
|
|
||||||
// File does not exist
|
|
||||||
NOT_FOUND = 2,
|
|
||||||
// Device does not have a filesystem
|
|
||||||
NO_FILESYSTEM = 3,
|
|
||||||
// File exists, but could not decode protobufs
|
|
||||||
DECODE_FAILED = 4,
|
|
||||||
// File exists, but open failed for some reason
|
|
||||||
OTHER_FAILURE = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cross platform filesystem API
|
// Cross platform filesystem API
|
||||||
|
|
||||||
#if defined(ARCH_PORTDUINO)
|
#if defined(ARCH_PORTDUINO)
|
||||||
@@ -68,8 +55,4 @@ bool renameFile(const char *pathFrom, const char *pathTo);
|
|||||||
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
||||||
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
||||||
void rmDir(const char *dirname);
|
void rmDir(const char *dirname);
|
||||||
void setupSDCard();
|
void setupSDCard();
|
||||||
LoadFileResult loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
|
||||||
|
|
||||||
bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct,
|
|
||||||
bool fullAtomic = true);
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#if HAS_SCREEN
|
#if HAS_SCREEN
|
||||||
#include "ClockRenderer.h"
|
#include "ClockRenderer.h"
|
||||||
#include "FSCommon.h"
|
|
||||||
#include "GPS.h"
|
#include "GPS.h"
|
||||||
#include "MenuHandler.h"
|
#include "MenuHandler.h"
|
||||||
#include "MeshRadio.h"
|
#include "MeshRadio.h"
|
||||||
@@ -1790,7 +1789,7 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
|||||||
|
|
||||||
void menuHandler::saveUIConfig()
|
void menuHandler::saveUIConfig()
|
||||||
{
|
{
|
||||||
saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig);
|
nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
|||||||
@@ -62,12 +62,22 @@ void InkHUD::HeardApplet::populateFromNodeDB()
|
|||||||
{
|
{
|
||||||
// Fill a collection with pointers to each node in db
|
// Fill a collection with pointers to each node in db
|
||||||
std::vector<meshtastic_NodeInfoLite *> ordered;
|
std::vector<meshtastic_NodeInfoLite *> ordered;
|
||||||
for (int i = 1; i < maxCards(); i++) {
|
for (auto mn = nodeDB->meshNodes->begin(); mn != nodeDB->meshNodes->end(); ++mn) {
|
||||||
auto mn = nodeDB->getMeshNodeByIndex(i);
|
// Only copy if valid, and not our own node
|
||||||
if (mn->num != 0 && mn->num != nodeDB->getNodeNum())
|
if (mn->num != 0 && mn->num != nodeDB->getNodeNum())
|
||||||
ordered.push_back(&*mn);
|
ordered.push_back(&*mn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort the collection by age
|
||||||
|
std::sort(ordered.begin(), ordered.end(), [](meshtastic_NodeInfoLite *top, meshtastic_NodeInfoLite *bottom) -> bool {
|
||||||
|
return (top->last_heard > bottom->last_heard);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Keep the most recent entries only
|
||||||
|
// Just enough to fill the screen
|
||||||
|
if (ordered.size() > maxCards())
|
||||||
|
ordered.resize(maxCards());
|
||||||
|
|
||||||
// Create card info for these (stale) node observations
|
// Create card info for these (stale) node observations
|
||||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
for (meshtastic_NodeInfoLite *node : ordered) {
|
for (meshtastic_NodeInfoLite *node : ordered) {
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ void CannedMessageStore::load()
|
|||||||
|
|
||||||
// Attempt to load the bulk canned message data from flash
|
// Attempt to load the bulk canned message data from flash
|
||||||
meshtastic_CannedMessageModuleConfig cannedMessageModuleConfig;
|
meshtastic_CannedMessageModuleConfig cannedMessageModuleConfig;
|
||||||
LoadFileResult result = loadProto("/prefs/cannedConf.proto", meshtastic_CannedMessageModuleConfig_size,
|
LoadFileResult result = nodeDB->loadProto("/prefs/cannedConf.proto", meshtastic_CannedMessageModuleConfig_size,
|
||||||
sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg,
|
sizeof(meshtastic_CannedMessageModuleConfig),
|
||||||
&cannedMessageModuleConfig);
|
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
||||||
|
|
||||||
// Abort if nothing to load
|
// Abort if nothing to load
|
||||||
if (result != LoadFileResult::LOAD_SUCCESS || strlen(cannedMessageModuleConfig.messages) == 0)
|
if (result != LoadFileResult::LOAD_SUCCESS || strlen(cannedMessageModuleConfig.messages) == 0)
|
||||||
@@ -129,8 +129,8 @@ void CannedMessageStore::handleSet(const meshtastic_AdminMessage *request)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Write to flash
|
// Write to flash
|
||||||
saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size, &meshtastic_CannedMessageModuleConfig_msg,
|
nodeDB->saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||||
&cannedMessageModuleConfig);
|
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
||||||
|
|
||||||
// Reload from flash, to update the canned messages in RAM
|
// Reload from flash, to update the canned messages in RAM
|
||||||
// (This is a lazy way to handle it)
|
// (This is a lazy way to handle it)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
|
#include "SafeFile.h"
|
||||||
#include "TypeConversions.h"
|
#include "TypeConversions.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
@@ -313,7 +314,7 @@ NodeDB::NodeDB()
|
|||||||
LOG_DEBUG("Number of Device Reboots: %d", myNodeInfo.reboot_count);
|
LOG_DEBUG("Number of Device Reboots: %d", myNodeInfo.reboot_count);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_resetRadioConfig(); // If bogus settings got saved, then fix them
|
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||||
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);
|
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);
|
||||||
|
|
||||||
// Uncomment below to always enable UDP broadcasts
|
// Uncomment below to always enable UDP broadcasts
|
||||||
@@ -424,13 +425,13 @@ NodeDB::NodeDB()
|
|||||||
config.has_position = true;
|
config.has_position = true;
|
||||||
info->has_position = true;
|
info->has_position = true;
|
||||||
info->position = TypeConversions::ConvertToPositionLite(fixedGPS);
|
info->position = TypeConversions::ConvertToPositionLite(fixedGPS);
|
||||||
nodeDB->_setLocalPosition(fixedGPS);
|
nodeDB->setLocalPosition(fixedGPS);
|
||||||
config.position.fixed_position = true;
|
config.position.fixed_position = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sortMeshDB();
|
sortMeshDB();
|
||||||
_saveToDisk(saveWhat);
|
saveToDisk(saveWhat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -459,7 +460,7 @@ bool isBroadcast(uint32_t dest)
|
|||||||
return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA;
|
return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::_resetRadioConfig(bool is_fresh_install)
|
void NodeDB::resetRadioConfig(bool is_fresh_install)
|
||||||
{
|
{
|
||||||
if (is_fresh_install) {
|
if (is_fresh_install) {
|
||||||
radioGeneration++;
|
radioGeneration++;
|
||||||
@@ -479,7 +480,6 @@ void NodeDB::_resetRadioConfig(bool is_fresh_install)
|
|||||||
|
|
||||||
bool NodeDB::factoryReset(bool eraseBleBonds)
|
bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||||
{
|
{
|
||||||
FUNCTION_START("factoryReset");
|
|
||||||
LOG_INFO("Perform factory reset!");
|
LOG_INFO("Perform factory reset!");
|
||||||
// first, remove the "/prefs" (this removes most prefs)
|
// first, remove the "/prefs" (this removes most prefs)
|
||||||
spiLock->lock();
|
spiLock->lock();
|
||||||
@@ -498,7 +498,7 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
|
|||||||
installDefaultModuleConfig();
|
installDefaultModuleConfig();
|
||||||
installDefaultChannels();
|
installDefaultChannels();
|
||||||
// third, write everything to disk
|
// third, write everything to disk
|
||||||
_saveToDisk();
|
saveToDisk();
|
||||||
if (eraseBleBonds) {
|
if (eraseBleBonds) {
|
||||||
LOG_INFO("Erase BLE bonds");
|
LOG_INFO("Erase BLE bonds");
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -513,7 +513,6 @@ bool NodeDB::factoryReset(bool eraseBleBonds)
|
|||||||
Bluefruit.Central.clearBonds();
|
Bluefruit.Central.clearBonds();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,7 +649,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
config.device.node_info_broadcast_secs = default_node_info_broadcast_secs;
|
config.device.node_info_broadcast_secs = default_node_info_broadcast_secs;
|
||||||
config.security.serial_enabled = true;
|
config.security.serial_enabled = true;
|
||||||
config.security.admin_channel_enabled = false;
|
config.security.admin_channel_enabled = false;
|
||||||
_resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh
|
resetRadioConfig(true); // This also triggers NodeInfo/Position requests since we're fresh
|
||||||
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
|
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
|
||||||
|
|
||||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
|
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
|
||||||
@@ -747,7 +746,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
|||||||
|
|
||||||
#ifdef USERPREFS_CONFIG_DEVICE_ROLE
|
#ifdef USERPREFS_CONFIG_DEVICE_ROLE
|
||||||
// Apply role-specific defaults when role is set via user preferences
|
// Apply role-specific defaults when role is set via user preferences
|
||||||
_installRoleDefaults(config.device.role);
|
installRoleDefaults(config.device.role);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
initConfigIntervals();
|
initConfigIntervals();
|
||||||
@@ -905,7 +904,7 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
initModuleConfigIntervals();
|
initModuleConfigIntervals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::_installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
||||||
{
|
{
|
||||||
if (role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
|
if (role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
|
||||||
initConfigIntervals();
|
initConfigIntervals();
|
||||||
@@ -991,7 +990,6 @@ void NodeDB::installDefaultChannels()
|
|||||||
|
|
||||||
void NodeDB::resetNodes(bool keepFavorites)
|
void NodeDB::resetNodes(bool keepFavorites)
|
||||||
{
|
{
|
||||||
FUNCTION_START("resetNodes");
|
|
||||||
if (!config.position.fixed_position)
|
if (!config.position.fixed_position)
|
||||||
clearLocalPosition();
|
clearLocalPosition();
|
||||||
numMeshNodes = 1;
|
numMeshNodes = 1;
|
||||||
@@ -1015,12 +1013,10 @@ void NodeDB::resetNodes(bool keepFavorites)
|
|||||||
saveDeviceStateToDisk();
|
saveDeviceStateToDisk();
|
||||||
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
|
||||||
neighborInfoModule->resetNeighbors();
|
neighborInfoModule->resetNeighbors();
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::removeNodeByNum(NodeNum nodeNum)
|
void NodeDB::removeNodeByNum(NodeNum nodeNum)
|
||||||
{
|
{
|
||||||
FUNCTION_START("removeNodeByNum");
|
|
||||||
int newPos = 0, removed = 0;
|
int newPos = 0, removed = 0;
|
||||||
for (int i = 0; i < numMeshNodes; i++) {
|
for (int i = 0; i < numMeshNodes; i++) {
|
||||||
if (meshNodes->at(i).num != nodeNum)
|
if (meshNodes->at(i).num != nodeNum)
|
||||||
@@ -1033,17 +1029,16 @@ void NodeDB::removeNodeByNum(NodeNum nodeNum)
|
|||||||
meshtastic_NodeInfoLite());
|
meshtastic_NodeInfoLite());
|
||||||
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Save changes", removed);
|
LOG_DEBUG("NodeDB::removeNodeByNum purged %d entries. Save changes", removed);
|
||||||
saveNodeDatabaseToDisk();
|
saveNodeDatabaseToDisk();
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::_clearLocalPosition()
|
void NodeDB::clearLocalPosition()
|
||||||
{
|
{
|
||||||
meshtastic_NodeInfoLite *node = _getMeshNode(nodeDB->getNodeNum());
|
meshtastic_NodeInfoLite *node = getMeshNode(nodeDB->getNodeNum());
|
||||||
node->position.latitude_i = 0;
|
node->position.latitude_i = 0;
|
||||||
node->position.longitude_i = 0;
|
node->position.longitude_i = 0;
|
||||||
node->position.altitude = 0;
|
node->position.altitude = 0;
|
||||||
node->position.time = 0;
|
node->position.time = 0;
|
||||||
_setLocalPosition(meshtastic_Position_init_default);
|
setLocalPosition(meshtastic_Position_init_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::cleanupMeshDB()
|
void NodeDB::cleanupMeshDB()
|
||||||
@@ -1119,7 +1114,7 @@ void NodeDB::pickNewNodeNum()
|
|||||||
}
|
}
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *found;
|
meshtastic_NodeInfoLite *found;
|
||||||
while (((found = _getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0) ||
|
while (((found = getMeshNode(nodeNum)) && memcmp(found->user.macaddr, ourMacAddr, sizeof(ourMacAddr)) != 0) ||
|
||||||
(nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED)) {
|
(nodeNum == NODENUM_BROADCAST || nodeNum < NUM_RESERVED)) {
|
||||||
NodeNum candidate = random(NUM_RESERVED, LONG_MAX); // try a new random choice
|
NodeNum candidate = random(NUM_RESERVED, LONG_MAX); // try a new random choice
|
||||||
if (found)
|
if (found)
|
||||||
@@ -1133,6 +1128,39 @@ void NodeDB::pickNewNodeNum()
|
|||||||
myNodeInfo.my_node_num = nodeNum;
|
myNodeInfo.my_node_num = nodeNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Load a protobuf from a file, return LoadFileResult */
|
||||||
|
LoadFileResult NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields,
|
||||||
|
void *dest_struct)
|
||||||
|
{
|
||||||
|
LoadFileResult state = LoadFileResult::OTHER_FAILURE;
|
||||||
|
#ifdef FSCom
|
||||||
|
concurrency::LockGuard g(spiLock);
|
||||||
|
|
||||||
|
auto f = FSCom.open(filename, FILE_O_READ);
|
||||||
|
|
||||||
|
if (f) {
|
||||||
|
LOG_INFO("Load %s", filename);
|
||||||
|
pb_istream_t stream = {&readcb, &f, protoSize};
|
||||||
|
if (fields != &meshtastic_NodeDatabase_msg) // contains a vector object
|
||||||
|
memset(dest_struct, 0, objSize);
|
||||||
|
if (!pb_decode(&stream, fields, dest_struct)) {
|
||||||
|
LOG_ERROR("Error: can't decode protobuf %s", PB_GET_ERROR(&stream));
|
||||||
|
state = LoadFileResult::DECODE_FAILED;
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Loaded %s successfully", filename);
|
||||||
|
state = LoadFileResult::LOAD_SUCCESS;
|
||||||
|
}
|
||||||
|
f.close();
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("Could not open / read %s", filename);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
LOG_ERROR("ERROR: Filesystem not implemented");
|
||||||
|
state = LoadFileResult::NO_FILESYSTEM;
|
||||||
|
#endif
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
void NodeDB::loadFromDisk()
|
void NodeDB::loadFromDisk()
|
||||||
{
|
{
|
||||||
// Mark the current device state as completely unusable, so that if we fail reading the entire file from
|
// Mark the current device state as completely unusable, so that if we fail reading the entire file from
|
||||||
@@ -1232,7 +1260,7 @@ void NodeDB::loadFromDisk()
|
|||||||
if (backupSecurity.private_key.size > 0) {
|
if (backupSecurity.private_key.size > 0) {
|
||||||
LOG_DEBUG("Restoring backup of security config");
|
LOG_DEBUG("Restoring backup of security config");
|
||||||
config.security = backupSecurity;
|
config.security = backupSecurity;
|
||||||
_saveToDisk(SEGMENT_CONFIG);
|
saveToDisk(SEGMENT_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we load hard coded admin keys even when the configuration file has none.
|
// Make sure we load hard coded admin keys even when the configuration file has none.
|
||||||
@@ -1283,7 +1311,7 @@ void NodeDB::loadFromDisk()
|
|||||||
if (numAdminKeys > 0) {
|
if (numAdminKeys > 0) {
|
||||||
LOG_INFO("Saving %d hard coded admin keys.", numAdminKeys);
|
LOG_INFO("Saving %d hard coded admin keys.", numAdminKeys);
|
||||||
config.security.admin_key_count = numAdminKeys;
|
config.security.admin_key_count = numAdminKeys;
|
||||||
_saveToDisk(SEGMENT_CONFIG);
|
saveToDisk(SEGMENT_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
|
state = loadProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, sizeof(meshtastic_LocalModuleConfig),
|
||||||
@@ -1335,7 +1363,7 @@ void NodeDB::loadFromDisk()
|
|||||||
if (moduleConfig.paxcounter.paxcounter_update_interval == 900)
|
if (moduleConfig.paxcounter.paxcounter_update_interval == 900)
|
||||||
moduleConfig.paxcounter.paxcounter_update_interval = 0;
|
moduleConfig.paxcounter.paxcounter_update_interval = 0;
|
||||||
|
|
||||||
_saveToDisk(SEGMENT_MODULECONFIG);
|
saveToDisk(SEGMENT_MODULECONFIG);
|
||||||
}
|
}
|
||||||
#if ARCH_PORTDUINO
|
#if ARCH_PORTDUINO
|
||||||
// set any config overrides
|
// set any config overrides
|
||||||
@@ -1346,6 +1374,34 @@ void NodeDB::loadFromDisk()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Save a protobuf from a file, return true for success */
|
||||||
|
bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct,
|
||||||
|
bool fullAtomic)
|
||||||
|
{
|
||||||
|
bool okay = false;
|
||||||
|
#ifdef FSCom
|
||||||
|
auto f = SafeFile(filename, fullAtomic);
|
||||||
|
|
||||||
|
LOG_INFO("Save %s", filename);
|
||||||
|
pb_ostream_t stream = {&writecb, static_cast<Print *>(&f), protoSize};
|
||||||
|
|
||||||
|
if (!pb_encode(&stream, fields, dest_struct)) {
|
||||||
|
LOG_ERROR("Error: can't encode protobuf %s", PB_GET_ERROR(&stream));
|
||||||
|
} else {
|
||||||
|
okay = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeSucceeded = f.close();
|
||||||
|
|
||||||
|
if (!okay || !writeSucceeded) {
|
||||||
|
LOG_ERROR("Can't write prefs!");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
LOG_ERROR("ERROR: Filesystem not implemented");
|
||||||
|
#endif
|
||||||
|
return okay;
|
||||||
|
}
|
||||||
|
|
||||||
bool NodeDB::saveChannelsToDisk()
|
bool NodeDB::saveChannelsToDisk()
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -1434,7 +1490,7 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeDB::_saveToDisk(int saveWhat)
|
bool NodeDB::saveToDisk(int saveWhat)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Save to disk %d", saveWhat);
|
LOG_DEBUG("Save to disk %d", saveWhat);
|
||||||
bool success = saveToDiskNoRetry(saveWhat);
|
bool success = saveToDiskNoRetry(saveWhat);
|
||||||
@@ -1458,12 +1514,10 @@ bool NodeDB::_saveToDisk(int saveWhat)
|
|||||||
|
|
||||||
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
|
||||||
{
|
{
|
||||||
FUNCTION_START("readNextMeshNode");
|
|
||||||
meshtastic_NodeInfoLite *retVal = nullptr;
|
|
||||||
if (readIndex < numMeshNodes)
|
if (readIndex < numMeshNodes)
|
||||||
retVal = &meshNodes->at(readIndex++);
|
return &meshNodes->at(readIndex++);
|
||||||
FUNCTION_END;
|
else
|
||||||
return retVal;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||||
@@ -1491,7 +1545,7 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
|
|||||||
|
|
||||||
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
|
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
|
||||||
|
|
||||||
size_t NodeDB::_getNumOnlineMeshNodes(bool localOnly)
|
size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
||||||
{
|
{
|
||||||
size_t numseen = 0;
|
size_t numseen = 0;
|
||||||
|
|
||||||
@@ -1513,10 +1567,8 @@ size_t NodeDB::_getNumOnlineMeshNodes(bool localOnly)
|
|||||||
*/
|
*/
|
||||||
void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src)
|
void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSource src)
|
||||||
{
|
{
|
||||||
FUNCTION_START("updatePosition");
|
|
||||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
FUNCTION_END;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,7 +1577,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
|
|||||||
LOG_INFO("updatePosition LOCAL pos@%x time=%u lat=%d lon=%d alt=%d", p.timestamp, p.time, p.latitude_i, p.longitude_i,
|
LOG_INFO("updatePosition LOCAL pos@%x time=%u lat=%d lon=%d alt=%d", p.timestamp, p.time, p.latitude_i, p.longitude_i,
|
||||||
p.altitude);
|
p.altitude);
|
||||||
|
|
||||||
_setLocalPosition(p);
|
setLocalPosition(p);
|
||||||
info->position = TypeConversions::ConvertToPositionLite(p);
|
info->position = TypeConversions::ConvertToPositionLite(p);
|
||||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
|
} 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
|
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
||||||
@@ -1552,8 +1604,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
|
|||||||
}
|
}
|
||||||
info->has_position = true;
|
info->has_position = true;
|
||||||
updateGUIforNode = info;
|
updateGUIforNode = info;
|
||||||
_notifyObservers(true); // Force an update whether or not our node counts have changed
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update telemetry info for this node based on received metrics
|
/** Update telemetry info for this node based on received metrics
|
||||||
@@ -1561,11 +1612,9 @@ void NodeDB::updatePosition(uint32_t nodeId, const meshtastic_Position &p, RxSou
|
|||||||
*/
|
*/
|
||||||
void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src)
|
void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxSource src)
|
||||||
{
|
{
|
||||||
FUNCTION_START("updatePosition");
|
|
||||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
||||||
// Environment metrics should never go to NodeDb but we'll safegaurd anyway
|
// Environment metrics should never go to NodeDb but we'll safegaurd anyway
|
||||||
if (!info || t.which_variant != meshtastic_Telemetry_device_metrics_tag) {
|
if (!info || t.which_variant != meshtastic_Telemetry_device_metrics_tag) {
|
||||||
FUNCTION_END;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1578,8 +1627,7 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
|
|||||||
info->device_metrics = t.variant.device_metrics;
|
info->device_metrics = t.variant.device_metrics;
|
||||||
info->has_device_metrics = true;
|
info->has_device_metrics = true;
|
||||||
updateGUIforNode = info;
|
updateGUIforNode = info;
|
||||||
_notifyObservers(true); // Force an update whether or not our node counts have changed
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1587,10 +1635,8 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
|
|||||||
*/
|
*/
|
||||||
void NodeDB::addFromContact(meshtastic_SharedContact contact)
|
void NodeDB::addFromContact(meshtastic_SharedContact contact)
|
||||||
{
|
{
|
||||||
FUNCTION_START("addFromContact");
|
|
||||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(contact.node_num);
|
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(contact.node_num);
|
||||||
if (!info || !contact.has_user) {
|
if (!info || !contact.has_user) {
|
||||||
FUNCTION_END;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If the local node has this node marked as manually verified
|
// If the local node has this node marked as manually verified
|
||||||
@@ -1599,7 +1645,6 @@ void NodeDB::addFromContact(meshtastic_SharedContact contact)
|
|||||||
if ((info->bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK) && !contact.manually_verified) {
|
if ((info->bitfield & NODEINFO_BITFIELD_IS_KEY_MANUALLY_VERIFIED_MASK) && !contact.manually_verified) {
|
||||||
if (contact.user.public_key.size != info->user.public_key.size ||
|
if (contact.user.public_key.size != info->user.public_key.size ||
|
||||||
memcmp(contact.user.public_key.bytes, info->user.public_key.bytes, info->user.public_key.size) != 0) {
|
memcmp(contact.user.public_key.bytes, info->user.public_key.bytes, info->user.public_key.size) != 0) {
|
||||||
FUNCTION_END;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1643,26 +1688,22 @@ void NodeDB::addFromContact(meshtastic_SharedContact contact)
|
|||||||
// Mark the node's key as manually verified to indicate trustworthiness.
|
// Mark the node's key as manually verified to indicate trustworthiness.
|
||||||
updateGUIforNode = info;
|
updateGUIforNode = info;
|
||||||
sortMeshDB();
|
sortMeshDB();
|
||||||
_notifyObservers(true); // Force an update whether or not our node counts have changed
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
}
|
}
|
||||||
saveNodeDatabaseToDisk();
|
saveNodeDatabaseToDisk();
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update user info and channel for this node based on received user data
|
/** Update user info and channel for this node based on received user data
|
||||||
*/
|
*/
|
||||||
bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelIndex)
|
bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelIndex)
|
||||||
{
|
{
|
||||||
FUNCTION_START("updateUser");
|
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(nodeId);
|
||||||
if (!info) {
|
if (!info) {
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(MESHTASTIC_EXCLUDE_PKI)
|
#if !(MESHTASTIC_EXCLUDE_PKI)
|
||||||
if (p.public_key.size == 32 && nodeId != getNodeNum()) {
|
if (p.public_key.size == 32 && nodeId != nodeDB->getNodeNum()) {
|
||||||
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
printBytes("Incoming Pubkey: ", p.public_key.bytes, 32);
|
||||||
|
|
||||||
// Alert the user if a remote node is advertising public key that matches our own
|
// Alert the user if a remote node is advertising public key that matches our own
|
||||||
@@ -1679,7 +1720,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
sprintf(cn->message, warning, p.long_name);
|
sprintf(cn->message, warning, p.long_name);
|
||||||
service->sendClientNotification(cn);
|
service->sendClientNotification(cn);
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1687,7 +1727,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
// if the key doesn't match, don't update nodeDB at all.
|
// if the key doesn't match, don't update nodeDB at all.
|
||||||
if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) {
|
if (p.public_key.size != 32 || (memcmp(p.public_key.bytes, info->user.public_key.bytes, 32) != 0)) {
|
||||||
LOG_WARN("Public Key mismatch, dropping NodeInfo");
|
LOG_WARN("Public Key mismatch, dropping NodeInfo");
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOG_INFO("Public Key set for node, not updating!");
|
LOG_INFO("Public Key set for node, not updating!");
|
||||||
@@ -1715,19 +1754,19 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
updateGUIforNode = info;
|
updateGUIforNode = info;
|
||||||
_notifyObservers(true); // Force an update whether or not our node counts have changed
|
notifyObservers(true); // Force an update whether or not our node counts have changed
|
||||||
|
|
||||||
// We just changed something about a User,
|
// We just changed something about a User,
|
||||||
// store our DB unless we just did so less than a minute ago
|
// store our DB unless we just did so less than a minute ago
|
||||||
|
|
||||||
if (!Throttle::isWithinTimespanMs(lastNodeDbSave, ONE_MINUTE_MS)) {
|
if (!Throttle::isWithinTimespanMs(lastNodeDbSave, ONE_MINUTE_MS)) {
|
||||||
_saveToDisk(SEGMENT_NODEDATABASE);
|
saveToDisk(SEGMENT_NODEDATABASE);
|
||||||
lastNodeDbSave = millis();
|
lastNodeDbSave = millis();
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Defer NodeDB saveToDisk for now");
|
LOG_DEBUG("Defer NodeDB saveToDisk for now");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1735,121 +1774,107 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde
|
|||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
void NodeDB::updateFrom(const meshtastic_MeshPacket &mp)
|
||||||
{
|
{
|
||||||
FUNCTION_START("updateFrom");
|
|
||||||
if (mp.from == getNodeNum()) {
|
if (mp.from == getNodeNum()) {
|
||||||
LOG_DEBUG("Ignore update from self");
|
LOG_DEBUG("Ignore update from self");
|
||||||
} else if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
return;
|
||||||
|
}
|
||||||
|
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
|
||||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u", mp.from, mp.rx_time);
|
LOG_DEBUG("Update DB node 0x%x, rx_time=%u", mp.from, mp.rx_time);
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp));
|
meshtastic_NodeInfoLite *info = getOrCreateMeshNode(getFrom(&mp));
|
||||||
if (info) {
|
if (!info) {
|
||||||
if (mp.rx_time) // if the packet has a valid timestamp use it to update our last_heard
|
return;
|
||||||
info->last_heard = mp.rx_time;
|
|
||||||
|
|
||||||
if (mp.rx_snr)
|
|
||||||
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
|
|
||||||
|
|
||||||
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
|
|
||||||
|
|
||||||
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
|
|
||||||
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start) {
|
|
||||||
info->has_hops_away = true;
|
|
||||||
info->hops_away = mp.hop_start - mp.hop_limit;
|
|
||||||
}
|
|
||||||
sortMeshDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mp.rx_time) // if the packet has a valid timestamp use it to update our last_heard
|
||||||
|
info->last_heard = mp.rx_time;
|
||||||
|
|
||||||
|
if (mp.rx_snr)
|
||||||
|
info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
|
||||||
|
|
||||||
|
info->via_mqtt = mp.via_mqtt; // Store if we received this packet via MQTT
|
||||||
|
|
||||||
|
// If hopStart was set and there wasn't someone messing with the limit in the middle, add hopsAway
|
||||||
|
if (mp.hop_start != 0 && mp.hop_limit <= mp.hop_start) {
|
||||||
|
info->has_hops_away = true;
|
||||||
|
info->hops_away = mp.hop_start - mp.hop_limit;
|
||||||
|
}
|
||||||
|
sortMeshDB();
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::set_favorite(bool is_favorite, uint32_t nodeId)
|
void NodeDB::set_favorite(bool is_favorite, uint32_t nodeId)
|
||||||
{
|
{
|
||||||
FUNCTION_START("set_favorite");
|
meshtastic_NodeInfoLite *lite = getMeshNode(nodeId);
|
||||||
meshtastic_NodeInfoLite *lite = _getMeshNode(nodeId);
|
|
||||||
if (lite && lite->is_favorite != is_favorite) {
|
if (lite && lite->is_favorite != is_favorite) {
|
||||||
lite->is_favorite = is_favorite;
|
lite->is_favorite = is_favorite;
|
||||||
sortMeshDB();
|
sortMeshDB();
|
||||||
saveNodeDatabaseToDisk();
|
saveNodeDatabaseToDisk();
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if nodeId is_favorite; false if not or not found
|
|
||||||
bool NodeDB::isFavorite(uint32_t nodeId)
|
bool NodeDB::isFavorite(uint32_t nodeId)
|
||||||
{
|
{
|
||||||
FUNCTION_START("set_favorite");
|
// returns true if nodeId is_favorite; false if not or not found
|
||||||
// NODENUM_BROADCAST will never be in the DB
|
|
||||||
if (nodeId == NODENUM_BROADCAST) {
|
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *lite = _getMeshNode(nodeId);
|
// NODENUM_BROADCAST will never be in the DB
|
||||||
|
if (nodeId == NODENUM_BROADCAST)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
meshtastic_NodeInfoLite *lite = getMeshNode(nodeId);
|
||||||
|
|
||||||
if (lite) {
|
if (lite) {
|
||||||
FUNCTION_END;
|
|
||||||
return lite->is_favorite;
|
return lite->is_favorite;
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeDB::isFromOrToFavoritedNode(const meshtastic_MeshPacket &p)
|
bool NodeDB::isFromOrToFavoritedNode(const meshtastic_MeshPacket &p)
|
||||||
{
|
{
|
||||||
FUNCTION_START("isFromOrToFavoritedNode");
|
|
||||||
// This method is logically equivalent to:
|
// This method is logically equivalent to:
|
||||||
// return isFavorite(p.from) || isFavorite(p.to);
|
// return isFavorite(p.from) || isFavorite(p.to);
|
||||||
// but is more efficient by:
|
// but is more efficient by:
|
||||||
// 1. doing only one pass through the database, instead of two
|
// 1. doing only one pass through the database, instead of two
|
||||||
// 2. exiting early when a favorite is found, or if both from and to have been seen
|
// 2. exiting early when a favorite is found, or if both from and to have been seen
|
||||||
|
|
||||||
|
if (p.to == NODENUM_BROADCAST)
|
||||||
|
return isFavorite(p.from); // we never store NODENUM_BROADCAST in the DB, so we only need to check p.from
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *lite = NULL;
|
meshtastic_NodeInfoLite *lite = NULL;
|
||||||
|
|
||||||
bool seenFrom = false;
|
bool seenFrom = false;
|
||||||
bool seenTo = false;
|
bool seenTo = false;
|
||||||
|
|
||||||
if (p.to == NODENUM_BROADCAST)
|
|
||||||
seenTo = true;
|
|
||||||
|
|
||||||
for (int i = 0; i < numMeshNodes; i++) {
|
for (int i = 0; i < numMeshNodes; i++) {
|
||||||
lite = &meshNodes->at(i);
|
lite = &meshNodes->at(i);
|
||||||
|
|
||||||
if (!seenFrom && lite->num == p.from) {
|
if (lite->num == p.from) {
|
||||||
if (lite->is_favorite) {
|
if (lite->is_favorite)
|
||||||
FUNCTION_END;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
seenFrom = true;
|
seenFrom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!seenTo && lite->num == p.to) {
|
if (lite->num == p.to) {
|
||||||
if (lite->is_favorite) {
|
if (lite->is_favorite)
|
||||||
FUNCTION_END;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
seenTo = true;
|
seenTo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seenFrom && seenTo) {
|
if (seenFrom && seenTo)
|
||||||
FUNCTION_END;
|
|
||||||
return false; // we've seen both, and neither is a favorite, so we can stop searching early
|
return false; // we've seen both, and neither is a favorite, so we can stop searching early
|
||||||
}
|
|
||||||
|
|
||||||
// Note: if we knew that sortMeshDB was always called after any change to is_favorite, we could exit early after searching
|
// Note: if we knew that sortMeshDB was always called after any change to is_favorite, we could exit early after searching
|
||||||
// all favorited nodes first.
|
// all favorited nodes first.
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::pause_sort(bool paused)
|
void NodeDB::pause_sort(bool paused)
|
||||||
{
|
{
|
||||||
// Including the mutex macro for completeness, but it's possible it isn't appropriate here
|
|
||||||
FUNCTION_START("pause_sort");
|
|
||||||
sortingIsPaused = paused;
|
sortingIsPaused = paused;
|
||||||
FUNCTION_END;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeDB::sortMeshDB()
|
void NodeDB::sortMeshDB()
|
||||||
@@ -1884,13 +1909,10 @@ void NodeDB::sortMeshDB()
|
|||||||
|
|
||||||
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
|
||||||
{
|
{
|
||||||
FUNCTION_START("getMeshNodeChannel");
|
const meshtastic_NodeInfoLite *info = getMeshNode(n);
|
||||||
const meshtastic_NodeInfoLite *info = _getMeshNode(n);
|
|
||||||
if (!info) {
|
if (!info) {
|
||||||
FUNCTION_END;
|
|
||||||
return 0; // defaults to PRIMARY
|
return 0; // defaults to PRIMARY
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return info->channel;
|
return info->channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1903,7 +1925,7 @@ std::string NodeDB::getNodeId() const
|
|||||||
|
|
||||||
/// 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)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numMeshNodes; i++)
|
for (int i = 0; i < numMeshNodes; i++)
|
||||||
if (meshNodes->at(i).num == n)
|
if (meshNodes->at(i).num == n)
|
||||||
@@ -1913,7 +1935,7 @@ meshtastic_NodeInfoLite *NodeDB::_getMeshNode(NodeNum n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the maximum number of nodes is reached or we are running low on memory
|
// returns true if the maximum number of nodes is reached or we are running low on memory
|
||||||
bool NodeDB::_isFull()
|
bool NodeDB::isFull()
|
||||||
{
|
{
|
||||||
return (numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < MINIMUM_SAFE_FREE_HEAP);
|
return (numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < MINIMUM_SAFE_FREE_HEAP);
|
||||||
}
|
}
|
||||||
@@ -1921,7 +1943,7 @@ bool NodeDB::_isFull()
|
|||||||
/// Find a node in our DB, create an empty NodeInfo if missing
|
/// Find a node in our DB, create an empty NodeInfo if missing
|
||||||
meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||||
{
|
{
|
||||||
meshtastic_NodeInfoLite *lite = _getMeshNode(n);
|
meshtastic_NodeInfoLite *lite = getMeshNode(n);
|
||||||
|
|
||||||
if (!lite) {
|
if (!lite) {
|
||||||
if (isFull()) {
|
if (isFull()) {
|
||||||
@@ -1976,25 +1998,18 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
|||||||
/// valid lat/lon
|
/// valid lat/lon
|
||||||
bool NodeDB::hasValidPosition(const meshtastic_NodeInfoLite *n)
|
bool NodeDB::hasValidPosition(const meshtastic_NodeInfoLite *n)
|
||||||
{
|
{
|
||||||
FUNCTION_START("hasValidPosition");
|
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
||||||
auto retVal = n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If we have a node / user and they report is_licensed = true
|
/// If we have a node / user and they report is_licensed = true
|
||||||
/// we consider them licensed
|
/// we consider them licensed
|
||||||
UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
||||||
{
|
{
|
||||||
FUNCTION_START("getLicenseStatus");
|
meshtastic_NodeInfoLite *info = getMeshNode(nodeNum);
|
||||||
meshtastic_NodeInfoLite *info = _getMeshNode(nodeNum);
|
|
||||||
if (!info || !info->has_user) {
|
if (!info || !info->has_user) {
|
||||||
FUNCTION_END;
|
|
||||||
return UserLicenseStatus::NotKnown;
|
return UserLicenseStatus::NotKnown;
|
||||||
}
|
}
|
||||||
auto retVal = info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
@@ -2016,7 +2031,6 @@ bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_pub
|
|||||||
|
|
||||||
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
||||||
{
|
{
|
||||||
FUNCTION_START("backupPreferences");
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
lastBackupAttempt = millis();
|
lastBackupAttempt = millis();
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -2050,13 +2064,11 @@ bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
|||||||
// TODO: After more mainline SD card support
|
// TODO: After more mainline SD card support
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
FUNCTION_END;
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location, int restoreWhat)
|
bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location, int restoreWhat)
|
||||||
{
|
{
|
||||||
FUNCTION_START("backupPreferences");
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||||
@@ -2064,7 +2076,6 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
|||||||
if (!FSCom.exists(backupFileName)) {
|
if (!FSCom.exists(backupFileName)) {
|
||||||
spiLock->unlock();
|
spiLock->unlock();
|
||||||
LOG_WARN("Could not restore. No backup file found");
|
LOG_WARN("Could not restore. No backup file found");
|
||||||
FUNCTION_END;
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
spiLock->unlock();
|
spiLock->unlock();
|
||||||
@@ -2090,7 +2101,7 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
|||||||
LOG_DEBUG("Restored channels");
|
LOG_DEBUG("Restored channels");
|
||||||
}
|
}
|
||||||
|
|
||||||
success = _saveToDisk(restoreWhat);
|
success = saveToDisk(restoreWhat);
|
||||||
if (success) {
|
if (success) {
|
||||||
LOG_INFO("Restored preferences from backup");
|
LOG_INFO("Restored preferences from backup");
|
||||||
} else {
|
} else {
|
||||||
@@ -2102,7 +2113,6 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
|||||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||||
// TODO: After more mainline SD card support
|
// TODO: After more mainline SD card support
|
||||||
}
|
}
|
||||||
FUNCTION_END;
|
|
||||||
return success;
|
return success;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,6 @@
|
|||||||
#include "PortduinoGlue.h"
|
#include "PortduinoGlue.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FUNCTION_START(FUNCTION_NAME) \
|
|
||||||
if (fakeMutex) \
|
|
||||||
LOG_ERROR("Concurrency violation in " FUNCTION_NAME); \
|
|
||||||
fakeMutex = true;
|
|
||||||
|
|
||||||
#define FUNCTION_END fakeMutex = false;
|
|
||||||
|
|
||||||
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
// E3B0C442 is the blank hash
|
// E3B0C442 is the blank hash
|
||||||
static const uint8_t LOW_ENTROPY_HASHES[][32] = {
|
static const uint8_t LOW_ENTROPY_HASHES[][32] = {
|
||||||
@@ -117,6 +110,19 @@ uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
|
|||||||
/// Given a packet, return how many seconds in the past (vs now) it was received
|
/// Given a packet, return how many seconds in the past (vs now) it was received
|
||||||
uint32_t sinceReceived(const meshtastic_MeshPacket *p);
|
uint32_t sinceReceived(const meshtastic_MeshPacket *p);
|
||||||
|
|
||||||
|
enum LoadFileResult {
|
||||||
|
// Successfully opened the file
|
||||||
|
LOAD_SUCCESS = 1,
|
||||||
|
// File does not exist
|
||||||
|
NOT_FOUND = 2,
|
||||||
|
// Device does not have a filesystem
|
||||||
|
NO_FILESYSTEM = 3,
|
||||||
|
// File exists, but could not decode protobufs
|
||||||
|
DECODE_FAILED = 4,
|
||||||
|
// File exists, but open failed for some reason
|
||||||
|
OTHER_FAILURE = 5
|
||||||
|
};
|
||||||
|
|
||||||
enum UserLicenseStatus { NotKnown, NotLicensed, Licensed };
|
enum UserLicenseStatus { NotKnown, NotLicensed, Licensed };
|
||||||
|
|
||||||
class NodeDB
|
class NodeDB
|
||||||
@@ -129,6 +135,7 @@ class NodeDB
|
|||||||
// 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
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
std::vector<meshtastic_NodeInfoLite> *meshNodes;
|
||||||
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
|
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
|
||||||
meshtastic_NodeInfoLite *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
|
meshtastic_NodeInfoLite *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
|
||||||
Observable<const meshtastic::NodeStatus *> newStatus;
|
Observable<const meshtastic::NodeStatus *> newStatus;
|
||||||
@@ -144,26 +151,17 @@ class NodeDB
|
|||||||
/// write to flash
|
/// write to flash
|
||||||
/// @return true if the save was successful
|
/// @return true if the save was successful
|
||||||
bool saveToDisk(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS |
|
bool saveToDisk(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS |
|
||||||
SEGMENT_NODEDATABASE)
|
SEGMENT_NODEDATABASE);
|
||||||
{
|
|
||||||
FUNCTION_START("saveToDisk");
|
|
||||||
auto retVal = _saveToDisk(saveWhat);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reinit radio config if needed, because either:
|
/** Reinit radio config if needed, because either:
|
||||||
* a) sometimes a buggy android app might send us bogus settings or
|
* a) sometimes a buggy android app might send us bogus settings or
|
||||||
* b) the client set factory_reset
|
* b) the client set factory_reset
|
||||||
*
|
*
|
||||||
|
* @param factory_reset if true, reset all settings to factory defaults
|
||||||
* @param is_fresh_install set to true after a fresh install, to trigger NodeInfo/Position requests
|
* @param is_fresh_install set to true after a fresh install, to trigger NodeInfo/Position requests
|
||||||
|
* @return true if the config was completely reset, in that case, we should send it back to the client
|
||||||
*/
|
*/
|
||||||
void resetRadioConfig(bool is_fresh_install = false)
|
void resetRadioConfig(bool is_fresh_install = false);
|
||||||
{
|
|
||||||
FUNCTION_START("resetRadioConfig");
|
|
||||||
_resetRadioConfig(is_fresh_install);
|
|
||||||
FUNCTION_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// given a subpacket sniffed from the network, update our DB state
|
/// given a subpacket sniffed from the network, update our DB state
|
||||||
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
/// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
|
||||||
@@ -210,13 +208,7 @@ class NodeDB
|
|||||||
std::string getNodeId() const;
|
std::string getNodeId() const;
|
||||||
|
|
||||||
// @return last byte of a NodeNum, 0xFF if it ended at 0x00
|
// @return last byte of a NodeNum, 0xFF if it ended at 0x00
|
||||||
uint8_t getLastByteOfNodeNum(NodeNum num)
|
uint8_t getLastByteOfNodeNum(NodeNum num) { return (uint8_t)((num & 0xFF) ? (num & 0xFF) : 0xFF); }
|
||||||
{
|
|
||||||
FUNCTION_START("getLastByteOfNodeNum");
|
|
||||||
auto retVal = (uint8_t)((num & 0xFF) ? (num & 0xFF) : 0xFF);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use
|
/// if returns false, that means our node should send a DenyNodeNum response. If true, we think the number is okay for use
|
||||||
// bool handleWantNodeNum(NodeNum n);
|
// bool handleWantNodeNum(NodeNum n);
|
||||||
@@ -235,104 +227,79 @@ class NodeDB
|
|||||||
/* Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
/* Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
||||||
* @param localOnly if true, ignore nodes heard via MQTT
|
* @param localOnly if true, ignore nodes heard via MQTT
|
||||||
*/
|
*/
|
||||||
size_t getNumOnlineMeshNodes(bool localOnly = false)
|
size_t getNumOnlineMeshNodes(bool localOnly = false);
|
||||||
{
|
|
||||||
FUNCTION_START("getNumOnlineMeshNodes");
|
|
||||||
auto retVal = _getNumOnlineMeshNodes(localOnly);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetNodes(bool keepFavorites = false), removeNodeByNum(NodeNum nodeNum);
|
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes(bool keepFavorites = false),
|
||||||
|
removeNodeByNum(NodeNum nodeNum);
|
||||||
|
|
||||||
bool factoryReset(bool eraseBleBonds = false);
|
bool factoryReset(bool eraseBleBonds = false);
|
||||||
|
|
||||||
void installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
LoadFileResult loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields,
|
||||||
{
|
void *dest_struct);
|
||||||
FUNCTION_START("installRoleDefaults");
|
bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct,
|
||||||
_installRoleDefaults(role);
|
bool fullAtomic = true);
|
||||||
FUNCTION_END;
|
|
||||||
}
|
void installRoleDefaults(meshtastic_Config_DeviceConfig_Role role);
|
||||||
|
|
||||||
const meshtastic_NodeInfoLite *readNextMeshNode(uint32_t &readIndex);
|
const meshtastic_NodeInfoLite *readNextMeshNode(uint32_t &readIndex);
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *getMeshNodeByIndex(size_t x)
|
meshtastic_NodeInfoLite *getMeshNodeByIndex(size_t x)
|
||||||
{
|
{
|
||||||
FUNCTION_START("getMeshNodeByIndex");
|
assert(x < numMeshNodes);
|
||||||
meshtastic_NodeInfoLite *retValue = nullptr;
|
return &meshNodes->at(x);
|
||||||
if (x < numMeshNodes)
|
|
||||||
retValue = &meshNodes->at(x);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual meshtastic_NodeInfoLite *getMeshNode(NodeNum n)
|
virtual meshtastic_NodeInfoLite *getMeshNode(NodeNum n);
|
||||||
{
|
size_t getNumMeshNodes() { return numMeshNodes; }
|
||||||
FUNCTION_START("getMeshNode");
|
|
||||||
auto retVal = _getMeshNode(n);
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t getNumMeshNodes()
|
|
||||||
{
|
|
||||||
FUNCTION_START("getNumMeshNodes");
|
|
||||||
auto retVal = numMeshNodes;
|
|
||||||
FUNCTION_END;
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
UserLicenseStatus getLicenseStatus(uint32_t nodeNum);
|
UserLicenseStatus getLicenseStatus(uint32_t nodeNum);
|
||||||
|
|
||||||
// returns true if the maximum number of nodes is reached or we are running low on memory
|
size_t getMaxNodesAllocatedSize()
|
||||||
bool isFull()
|
|
||||||
{
|
{
|
||||||
FUNCTION_START("isFull");
|
meshtastic_NodeDatabase emptyNodeDatabase;
|
||||||
auto retVal = _isFull();
|
emptyNodeDatabase.version = DEVICESTATE_CUR_VER;
|
||||||
FUNCTION_END;
|
size_t nodeDatabaseSize;
|
||||||
return retVal;
|
pb_get_encoded_size(&nodeDatabaseSize, meshtastic_NodeDatabase_fields, &emptyNodeDatabase);
|
||||||
|
return nodeDatabaseSize + (MAX_NUM_NODES * meshtastic_NodeInfoLite_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearLocalPosition()
|
// returns true if the maximum number of nodes is reached or we are running low on memory
|
||||||
{
|
bool isFull();
|
||||||
FUNCTION_START("clearLocalPosition");
|
|
||||||
_clearLocalPosition();
|
void clearLocalPosition();
|
||||||
FUNCTION_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
void setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
||||||
{
|
{
|
||||||
FUNCTION_START("setLocalPosition");
|
if (timeOnly) {
|
||||||
_setLocalPosition(position, timeOnly);
|
LOG_DEBUG("Set local position time only: time=%u timestamp=%u", position.time, position.timestamp);
|
||||||
FUNCTION_END;
|
localPosition.time = position.time;
|
||||||
|
localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
|
||||||
|
position.time, position.timestamp);
|
||||||
|
localPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||||
|
|
||||||
|
#if !defined(MESHTASTIC_EXCLUDE_PKI)
|
||||||
|
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||||
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||||
|
|
||||||
|
/// Notify observers of changes to the DB
|
||||||
void notifyObservers(bool forceUpdate = false)
|
void notifyObservers(bool forceUpdate = false)
|
||||||
{
|
|
||||||
FUNCTION_START("notifyObservers");
|
|
||||||
_notifyObservers(forceUpdate);
|
|
||||||
FUNCTION_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool fakeMutex = false;
|
|
||||||
|
|
||||||
/// Notify observers of changes to the DB
|
|
||||||
void _notifyObservers(bool forceUpdate = false)
|
|
||||||
{
|
{
|
||||||
// Notify observers of the current node state
|
// Notify observers of the current node state
|
||||||
const meshtastic::NodeStatus status = meshtastic::NodeStatus(_getNumOnlineMeshNodes(), numMeshNodes, forceUpdate);
|
const meshtastic::NodeStatus status = meshtastic::NodeStatus(getNumOnlineMeshNodes(), getNumMeshNodes(), forceUpdate);
|
||||||
newStatus.notifyObservers(&status);
|
newStatus.notifyObservers(&status);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<meshtastic_NodeInfoLite> *meshNodes;
|
private:
|
||||||
|
|
||||||
bool duplicateWarned = false;
|
bool duplicateWarned = false;
|
||||||
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
uint32_t lastNodeDbSave = 0; // when we last saved our db to flash
|
||||||
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
|
uint32_t lastBackupAttempt = 0; // when we last tried a backup automatically or manually
|
||||||
@@ -366,51 +333,6 @@ class NodeDB
|
|||||||
bool saveDeviceStateToDisk();
|
bool saveDeviceStateToDisk();
|
||||||
bool saveNodeDatabaseToDisk();
|
bool saveNodeDatabaseToDisk();
|
||||||
void sortMeshDB();
|
void sortMeshDB();
|
||||||
|
|
||||||
void initConfigIntervals(), initModuleConfigIntervals();
|
|
||||||
|
|
||||||
size_t getMaxNodesAllocatedSize()
|
|
||||||
{
|
|
||||||
meshtastic_NodeDatabase emptyNodeDatabase;
|
|
||||||
emptyNodeDatabase.version = DEVICESTATE_CUR_VER;
|
|
||||||
size_t nodeDatabaseSize;
|
|
||||||
pb_get_encoded_size(&nodeDatabaseSize, meshtastic_NodeDatabase_fields, &emptyNodeDatabase);
|
|
||||||
return nodeDatabaseSize + (MAX_NUM_NODES * meshtastic_NodeInfoLite_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
|
||||||
|
|
||||||
// wrapped private functions:
|
|
||||||
|
|
||||||
bool _saveToDisk(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS |
|
|
||||||
SEGMENT_NODEDATABASE);
|
|
||||||
void _resetRadioConfig(bool is_fresh_install = false);
|
|
||||||
|
|
||||||
/* Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
|
||||||
* @param localOnly if true, ignore nodes heard via MQTT
|
|
||||||
*/
|
|
||||||
size_t _getNumOnlineMeshNodes(bool localOnly = false);
|
|
||||||
|
|
||||||
void _installRoleDefaults(meshtastic_Config_DeviceConfig_Role role);
|
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *_getMeshNode(NodeNum n);
|
|
||||||
|
|
||||||
bool _isFull();
|
|
||||||
|
|
||||||
void _clearLocalPosition();
|
|
||||||
|
|
||||||
void _setLocalPosition(meshtastic_Position position, bool timeOnly = false)
|
|
||||||
{
|
|
||||||
if (timeOnly) {
|
|
||||||
LOG_DEBUG("Set local position time only: time=%u timestamp=%u", position.time, position.timestamp);
|
|
||||||
localPosition.time = position.time;
|
|
||||||
localPosition.timestamp = position.timestamp > 0 ? position.timestamp : position.time;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG_DEBUG("Set local position: lat=%i lon=%i time=%u timestamp=%u", position.latitude_i, position.longitude_i,
|
|
||||||
position.time, position.timestamp);
|
|
||||||
localPosition = position;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NodeDB *nodeDB;
|
extern NodeDB *nodeDB;
|
||||||
|
|||||||
@@ -1322,7 +1322,7 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
|
|||||||
|
|
||||||
void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg)
|
void AdminModule::handleStoreDeviceUIConfig(const meshtastic_DeviceUIConfig &uicfg)
|
||||||
{
|
{
|
||||||
saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uicfg);
|
nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uicfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
|
void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
|
||||||
|
|||||||
@@ -2273,9 +2273,9 @@ ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &
|
|||||||
|
|
||||||
void CannedMessageModule::loadProtoForModule()
|
void CannedMessageModule::loadProtoForModule()
|
||||||
{
|
{
|
||||||
if (loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
if (nodeDB->loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||||
sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg,
|
sizeof(meshtastic_CannedMessageModuleConfig), &meshtastic_CannedMessageModuleConfig_msg,
|
||||||
&cannedMessageModuleConfig) != LoadFileResult::LOAD_SUCCESS) {
|
&cannedMessageModuleConfig) != LoadFileResult::LOAD_SUCCESS) {
|
||||||
installDefaultCannedMessageModuleConfig();
|
installDefaultCannedMessageModuleConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2295,8 +2295,8 @@ bool CannedMessageModule::saveProtoForModule()
|
|||||||
spiLock->unlock();
|
spiLock->unlock();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
okay &= saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
okay &= nodeDB->saveProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||||
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
&meshtastic_CannedMessageModuleConfig_msg, &cannedMessageModuleConfig);
|
||||||
|
|
||||||
return okay;
|
return okay;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
* @date [Insert Date]
|
* @date [Insert Date]
|
||||||
*/
|
*/
|
||||||
#include "ExternalNotificationModule.h"
|
#include "ExternalNotificationModule.h"
|
||||||
#include "FSCommon.h"
|
|
||||||
#include "MeshService.h"
|
#include "MeshService.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
@@ -371,8 +370,8 @@ ExternalNotificationModule::ExternalNotificationModule()
|
|||||||
if (inputBroker) // put our callback in the inputObserver list
|
if (inputBroker) // put our callback in the inputObserver list
|
||||||
inputObserver.observe(inputBroker);
|
inputObserver.observe(inputBroker);
|
||||||
#endif
|
#endif
|
||||||
if (loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig), &meshtastic_RTTTLConfig_msg,
|
if (nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
|
||||||
&rtttlConfig) != LoadFileResult::LOAD_SUCCESS) {
|
&meshtastic_RTTTLConfig_msg, &rtttlConfig) != LoadFileResult::LOAD_SUCCESS) {
|
||||||
memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone));
|
memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone));
|
||||||
// The default ringtone is always loaded from userPrefs.jsonc
|
// The default ringtone is always loaded from userPrefs.jsonc
|
||||||
strncpy(rtttlConfig.ringtone, USERPREFS_RINGTONE_RTTTL, sizeof(rtttlConfig.ringtone));
|
strncpy(rtttlConfig.ringtone, USERPREFS_RINGTONE_RTTTL, sizeof(rtttlConfig.ringtone));
|
||||||
@@ -641,7 +640,7 @@ void ExternalNotificationModule::handleSetRingtone(const char *from_msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
saveProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, &meshtastic_RTTTLConfig_msg, &rtttlConfig);
|
nodeDB->saveProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, &meshtastic_RTTTLConfig_msg, &rtttlConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "input/InputBroker.h"
|
#include "input/InputBroker.h"
|
||||||
|
|
||||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(CONFIG_IDF_TARGET_ESP32C6)
|
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
||||||
|
!defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||||
#include <NonBlockingRtttl.h>
|
#include <NonBlockingRtttl.h>
|
||||||
#else
|
#else
|
||||||
// Noop class for portduino.
|
// Noop class for portduino.
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ SerialModule::SerialModule() : StreamAPI(&Serial), concurrency::OSThread("Serial
|
|||||||
api_type = TYPE_SERIAL;
|
api_type = TYPE_SERIAL;
|
||||||
}
|
}
|
||||||
static Print *serialPrint = &Serial;
|
static Print *serialPrint = &Serial;
|
||||||
#elif defined(CONFIG_IDF_TARGET_ESP32C6) || defined(RAK3172) || defined(EBYTE_E77_MBL)
|
#elif defined(CONFIG_IDF_TARGET_ESP32C6) || defined(RAK3172) || defined(EBYTE_E77_MBL) || defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||||
SerialModule::SerialModule() : StreamAPI(&Serial1), concurrency::OSThread("Serial")
|
SerialModule::SerialModule() : StreamAPI(&Serial1), concurrency::OSThread("Serial")
|
||||||
{
|
{
|
||||||
api_type = TYPE_SERIAL;
|
api_type = TYPE_SERIAL;
|
||||||
@@ -175,7 +175,7 @@ int32_t SerialModule::runOnce()
|
|||||||
// Give it a chance to flush out 💩
|
// Give it a chance to flush out 💩
|
||||||
delay(10);
|
delay(10);
|
||||||
}
|
}
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C6)
|
#if defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||||
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
||||||
Serial1.setRxBufferSize(RX_BUFFER);
|
Serial1.setRxBufferSize(RX_BUFFER);
|
||||||
Serial1.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd);
|
Serial1.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd);
|
||||||
@@ -277,7 +277,7 @@ int32_t SerialModule::runOnce()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
#if defined(CONFIG_IDF_TARGET_ESP32C6)
|
#if defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||||
while (Serial1.available()) {
|
while (Serial1.available()) {
|
||||||
serialPayloadSize = Serial1.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
|
serialPayloadSize = Serial1.readBytes(serialBytes, meshtastic_Constants_DATA_PAYLOAD_LEN);
|
||||||
#else
|
#else
|
||||||
@@ -538,7 +538,7 @@ void SerialModule::processWXSerial()
|
|||||||
{
|
{
|
||||||
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
#if !defined(TTGO_T_ECHO) && !defined(T_ECHO_LITE) && !defined(CANARYONE) && !defined(CONFIG_IDF_TARGET_ESP32C6) && \
|
||||||
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \
|
!defined(MESHLINK) && !defined(ELECROW_ThinkNode_M1) && !defined(ELECROW_ThinkNode_M3) && !defined(ELECROW_ThinkNode_M5) && \
|
||||||
!defined(ARCH_STM32WL) && !defined(MUZI_BASE)
|
!defined(ARCH_STM32WL) && !defined(MUZI_BASE) && !defined(CONFIG_IDF_TARGET_ESP32H2)
|
||||||
static unsigned int lastAveraged = 0;
|
static unsigned int lastAveraged = 0;
|
||||||
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
static unsigned int averageIntervalMillis = 300000; // 5 minutes hard coded.
|
||||||
static double dir_sum_sin = 0;
|
static double dir_sum_sin = 0;
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ void esp32Setup()
|
|||||||
// #define APP_WATCHDOG_SECS 45
|
// #define APP_WATCHDOG_SECS 45
|
||||||
#define APP_WATCHDOG_SECS 90
|
#define APP_WATCHDOG_SECS 90
|
||||||
|
|
||||||
|
// esp_task_wdt_init returns an unknown error, so skip it on ESP32H2
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||||
esp_task_wdt_config_t *wdt_config = (esp_task_wdt_config_t *)malloc(sizeof(esp_task_wdt_config_t));
|
esp_task_wdt_config_t *wdt_config = (esp_task_wdt_config_t *)malloc(sizeof(esp_task_wdt_config_t));
|
||||||
wdt_config->timeout_ms = APP_WATCHDOG_SECS * 1000;
|
wdt_config->timeout_ms = APP_WATCHDOG_SECS * 1000;
|
||||||
@@ -181,7 +183,7 @@ void esp32Setup()
|
|||||||
#endif
|
#endif
|
||||||
res = esp_task_wdt_add(NULL);
|
res = esp_task_wdt_add(NULL);
|
||||||
assert(res == ESP_OK);
|
assert(res == ESP_OK);
|
||||||
|
#endif
|
||||||
#if HAS_32768HZ
|
#if HAS_32768HZ
|
||||||
enableSlowCLK();
|
enableSlowCLK();
|
||||||
#endif
|
#endif
|
||||||
@@ -223,9 +225,10 @@ void cpuDeepSleep(uint32_t msecToWake)
|
|||||||
13,
|
13,
|
||||||
#endif
|
#endif
|
||||||
34, 35, 37};
|
34, 35, 37};
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32H2
|
||||||
for (int i = 0; i < sizeof(rtcGpios); i++)
|
for (int i = 0; i < sizeof(rtcGpios); i++)
|
||||||
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
|
rtc_gpio_isolate((gpio_num_t)rtcGpios[i]);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
|
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
|
||||||
@@ -258,10 +261,10 @@ void cpuDeepSleep(uint32_t msecToWake)
|
|||||||
|
|
||||||
#endif // #end ESP32S3_WAKE_TYPE
|
#endif // #end ESP32S3_WAKE_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ESP_PD_DOMAIN_RTC_PERIPH
|
||||||
// We want RTC peripherals to stay on
|
// We want RTC peripherals to stay on
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
#endif
|
||||||
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
|
esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs
|
||||||
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,10 +388,10 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
|||||||
uint64_t sleepUsec = sleepMsec * 1000LL;
|
uint64_t sleepUsec = sleepMsec * 1000LL;
|
||||||
|
|
||||||
// NOTE! ESP docs say we must disable bluetooth and wifi before light sleep
|
// NOTE! ESP docs say we must disable bluetooth and wifi before light sleep
|
||||||
|
#ifdef ESP_PD_DOMAIN_RTC_PERIPH
|
||||||
// We want RTC peripherals to stay on
|
// We want RTC peripherals to stay on
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
#endif
|
||||||
#if defined(BUTTON_PIN) && defined(BUTTON_NEED_PULLUP)
|
#if defined(BUTTON_PIN) && defined(BUTTON_NEED_PULLUP)
|
||||||
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
gpio_pullup_en((gpio_num_t)BUTTON_PIN);
|
||||||
#endif
|
#endif
|
||||||
@@ -523,6 +523,8 @@ void enableModemSleep()
|
|||||||
esp32_config.max_freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ;
|
esp32_config.max_freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
esp32_config.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
|
esp32_config.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
esp32_config.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
esp32_config.max_freq_mhz = CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ;
|
esp32_config.max_freq_mhz = CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ;
|
||||||
#else
|
#else
|
||||||
|
|||||||
47
variants/esp32h2/esp32h2.ini
Normal file
47
variants/esp32h2/esp32h2.ini
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
[esp32h2_base]
|
||||||
|
extends = esp32_base
|
||||||
|
platform =
|
||||||
|
# Do not renovate until we have switched to pioarduino tagged builds
|
||||||
|
https://github.com/Jason2866/platform-espressif32/archive/39475a7213fa3a52b0c2048d1a31c215fc85fcf8.zip
|
||||||
|
build_flags =
|
||||||
|
${arduino_base.build_flags}
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
-Isrc/platform/esp32
|
||||||
|
-std=c++11
|
||||||
|
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||||
|
-DSERIAL_BUFFER_SIZE=4096
|
||||||
|
-DLIBPAX_ARDUINO
|
||||||
|
-DLIBPAX_WIFI
|
||||||
|
-DLIBPAX_BLE
|
||||||
|
-DMESHTASTIC_EXCLUDE_WEBSERVER
|
||||||
|
;-DDEBUG_HEAP
|
||||||
|
; TEMP
|
||||||
|
-DHAS_BLUETOOTH=0
|
||||||
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
|
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${arduino_base.lib_deps}
|
||||||
|
${networking_base.lib_deps}
|
||||||
|
${environmental_base.lib_deps}
|
||||||
|
${environmental_extra.lib_deps}
|
||||||
|
${radiolib_base.lib_deps}
|
||||||
|
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
|
||||||
|
lewisxhe/XPowersLib@0.3.1
|
||||||
|
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
|
||||||
|
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
|
||||||
|
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
|
||||||
|
rweather/Crypto@0.4.0
|
||||||
|
|
||||||
|
build_src_filter =
|
||||||
|
${esp32_base.build_src_filter} -<mesh/http>
|
||||||
|
|
||||||
|
monitor_speed = 460800
|
||||||
|
monitor_filters = esp32_h2_exception_decoder
|
||||||
|
|
||||||
|
lib_ignore =
|
||||||
|
NonBlockingRTTTL
|
||||||
|
NimBLE-Arduino
|
||||||
|
libpax
|
||||||
|
|
||||||
11
variants/esp32h2/waveshare-esp32-h2/platformio.ini
Normal file
11
variants/esp32h2/waveshare-esp32-h2/platformio.ini
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[env:waveshare-esp32h2]
|
||||||
|
extends = esp32h2_base
|
||||||
|
board = esp32-h2-devkitm-1
|
||||||
|
board_build.f_flash = 16000000L
|
||||||
|
board_level = pr
|
||||||
|
build_flags =
|
||||||
|
${esp32h2_base.build_flags}
|
||||||
|
-I variants/esp32h2/waveshare-esp32-h2
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
-DARDUINO_USB_MODE=1
|
||||||
|
-DHAS_WIFI=0
|
||||||
8
variants/esp32h2/waveshare-esp32-h2/variant.h
Normal file
8
variants/esp32h2/waveshare-esp32-h2/variant.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
#define HAS_SCREEN 0
|
||||||
|
#define HAS_WIFI 0
|
||||||
|
|
||||||
|
#define LORA_SCK 4
|
||||||
|
#define LORA_MISO 3
|
||||||
|
#define LORA_MOSI 2
|
||||||
|
#define LORA_CS 1
|
||||||
Reference in New Issue
Block a user