mirror of
https://github.com/meshtastic/firmware.git
synced 2026-06-05 18:08:45 +00:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9fce57e74d | |||
| 0533ca0eda | |||
| 661fcd0e77 | |||
| ac3980e98d | |||
| ff4b7fdce3 | |||
| b933b48898 | |||
| df52bbcae3 | |||
| 4a9f6ceb55 | |||
| db84fbed5d | |||
| 96663218ee | |||
| 51dc2da83c | |||
| 19951e3b6a | |||
| 0b106d4642 | |||
| 70d8da6561 | |||
| 5f5fac25fd | |||
| 9cdd6b8633 | |||
| f5db94e606 | |||
| 3f512976b8 | |||
| ad41f9e013 | |||
| b85d9f988e | |||
| 7150a68714 | |||
| 6cf8cbcda7 | |||
| 4e74c549ed | |||
| 065370c6b6 | |||
| f913ce0310 | |||
| 261c326da6 | |||
| eb3ffc1922 | |||
| c986c4a742 | |||
| cb0982c2f1 | |||
| ccbec44bfb | |||
| 109d66e976 | |||
| 320a38f9ac | |||
| 488e76d27b | |||
| ada8b96842 | |||
| c2cc3207ba | |||
| f309fba89c | |||
| 7dc0330897 | |||
| 6c227157b5 | |||
| e4c6aa588e | |||
| 164d46facb | |||
| 6c6b804b53 | |||
| 1a92b7881f | |||
| 1961bcaf9d | |||
| a7c4361d7c | |||
| c0145001ef | |||
| 01618e99e5 | |||
| a02d538b58 | |||
| ac9cb235a8 | |||
| 9ce19c5c1c | |||
| 022dc29ea7 | |||
| 18410ba80d | |||
| 3f3f89c06e | |||
| 919085379e | |||
| bdf60d8e4d | |||
| 431b067f30 | |||
| 4a63b36a7d | |||
| 1fe16a0471 | |||
| 2b1f45fd8b | |||
| 79c0e8168d | |||
| 459dbfff23 | |||
| 27ddd549f9 | |||
| e5ed913a8a | |||
| 93d041b4b0 | |||
| 005e8501ce | |||
| 6cb3acd79f | |||
| 910efd86f0 | |||
| ded45cf17d | |||
| 6f9e4d5b1a | |||
| b012e561eb | |||
| 9fd100dd92 | |||
| c756bea711 | |||
| 068d529298 | |||
| add75f073a | |||
| a00e272afe | |||
| 48b00188fb | |||
| 62058b650a | |||
| 147416045a | |||
| 72e991104e | |||
| 26a0612e37 | |||
| 6cfa5d8f29 | |||
| 2e21e49144 | |||
| aad9e352b7 | |||
| 368d811ea6 | |||
| 2996a9616f | |||
| 99e47cf73c | |||
| 102c328436 | |||
| 0cd4224033 | |||
| 20743ae2c4 | |||
| 51c5d8ce93 | |||
| b229d351cf | |||
| 350b82bc08 | |||
| d21b272680 | |||
| fe5d251393 | |||
| 66a98fb062 | |||
| d65d9305d3 | |||
| 34e5cf0d96 | |||
| b28db07409 | |||
| f753caf15d | |||
| 0c1838dde7 | |||
| b183febd3c | |||
| 87601f4760 | |||
| 0e3c419652 | |||
| 891bf643e2 | |||
| 143cdf4572 | |||
| d440dbd522 | |||
| 7e063c1dda | |||
| 988d8cd1ab | |||
| c98c682cff | |||
| 8023fec0ec |
+1
-1
Submodule lib/device-ui updated: 5c6156d2aa...cbe5c14e8a
+8
-1
@@ -7,16 +7,23 @@ static File openFile(const char *filename, bool fullAtomic)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
LOG_DEBUG("Opening %s, fullAtomic=%d", filename, fullAtomic);
|
||||
|
||||
#ifdef ARCH_NRF52
|
||||
FSCom.remove(filename);
|
||||
return FSCom.open(filename, FILE_O_WRITE);
|
||||
#endif
|
||||
if (!fullAtomic)
|
||||
if (!fullAtomic) {
|
||||
FSCom.remove(filename); // Nuke the old file to make space (ignore if it !exists)
|
||||
}
|
||||
|
||||
String filenameTmp = filename;
|
||||
filenameTmp += ".tmp";
|
||||
|
||||
// If we are doing a full atomic write, remove the old tmp file now
|
||||
if (fullAtomic) {
|
||||
FSCom.remove(filename);
|
||||
}
|
||||
|
||||
// clear any previous LFS errors
|
||||
return FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||
}
|
||||
|
||||
@@ -117,17 +117,13 @@ void MeshService::loop()
|
||||
}
|
||||
|
||||
/// The radioConfig object just changed, call this to force the hw to change to the new settings
|
||||
bool MeshService::reloadConfig(int saveWhat)
|
||||
void MeshService::reloadConfig(int saveWhat)
|
||||
{
|
||||
// If we can successfully set this radio to these settings, save them to disk
|
||||
|
||||
// This will also update the region as needed
|
||||
bool didReset = nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||
nodeDB->resetRadioConfig(); // Don't let the phone send us fatally bad settings
|
||||
|
||||
configChanged.notifyObservers(NULL); // This will cause radio hardware to change freqs etc
|
||||
nodeDB->saveToDisk(saveWhat);
|
||||
|
||||
return didReset;
|
||||
}
|
||||
|
||||
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
||||
|
||||
@@ -118,7 +118,7 @@ class MeshService
|
||||
/** The radioConfig object just changed, call this to force the hw to change to the new settings
|
||||
* @return true if client devices should be sent a new set of radio configs
|
||||
*/
|
||||
bool reloadConfig(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
void reloadConfig(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
|
||||
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
||||
void reloadOwner(bool shouldSave = true);
|
||||
|
||||
+119
-22
@@ -400,36 +400,20 @@ bool isBroadcast(uint32_t dest)
|
||||
return dest == NODENUM_BROADCAST || dest == NODENUM_BROADCAST_NO_LORA;
|
||||
}
|
||||
|
||||
bool NodeDB::resetRadioConfig(bool factory_reset, bool is_fresh_install)
|
||||
void NodeDB::resetRadioConfig(bool is_fresh_install)
|
||||
{
|
||||
bool didFactoryReset = false;
|
||||
|
||||
if (is_fresh_install) {
|
||||
radioGeneration++;
|
||||
}
|
||||
|
||||
if (factory_reset) {
|
||||
didFactoryReset = factoryReset();
|
||||
}
|
||||
|
||||
if (channelFile.channels_count != MAX_NUM_CHANNELS) {
|
||||
LOG_INFO("Set default channel and radio preferences!");
|
||||
|
||||
channels.initDefaults();
|
||||
}
|
||||
|
||||
channels.onConfigChanged();
|
||||
|
||||
// Update the global myRegion
|
||||
initRegion();
|
||||
|
||||
if (didFactoryReset) {
|
||||
LOG_INFO("Reboot due to factory reset");
|
||||
screen->startAlert("Rebooting...");
|
||||
rebootAtMsec = millis() + (5 * 1000);
|
||||
}
|
||||
|
||||
return didFactoryReset;
|
||||
}
|
||||
|
||||
bool NodeDB::factoryReset(bool eraseBleBonds)
|
||||
@@ -591,7 +575,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
|
||||
config.device.node_info_broadcast_secs = default_node_info_broadcast_secs;
|
||||
config.security.serial_enabled = true;
|
||||
config.security.admin_channel_enabled = false;
|
||||
resetRadioConfig(false, 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);
|
||||
|
||||
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR)) && \
|
||||
@@ -1047,6 +1031,9 @@ void NodeDB::loadFromDisk()
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
LOG_WARN("Devicestate %d is old, discard", devicestate.version);
|
||||
installDefaultDeviceState();
|
||||
} else if (state != LoadFileResult::LOAD_SUCCESS) {
|
||||
// If we have an owner in the backup, restore it
|
||||
restorePreferences(meshtastic_AdminMessage_BackupLocation_FLASH, SEGMENT_DEVICESTATE);
|
||||
} else {
|
||||
LOG_INFO("Loaded saved devicestate version %d", devicestate.version);
|
||||
}
|
||||
@@ -1055,6 +1042,7 @@ void NodeDB::loadFromDisk()
|
||||
&config);
|
||||
if (state != LoadFileResult::LOAD_SUCCESS) {
|
||||
installDefaultConfig(); // Our in RAM copy might now be corrupt
|
||||
restorePreferences(meshtastic_AdminMessage_BackupLocation_FLASH, SEGMENT_CONFIG);
|
||||
} else {
|
||||
if (config.version < DEVICESTATE_MIN_VER) {
|
||||
LOG_WARN("config %d is old, discard", config.version);
|
||||
@@ -1064,7 +1052,7 @@ void NodeDB::loadFromDisk()
|
||||
}
|
||||
}
|
||||
if (backupSecurity.private_key.size > 0) {
|
||||
LOG_DEBUG("Restoring backup of security config");
|
||||
LOG_DEBUG("Restoring security config");
|
||||
config.security = backupSecurity;
|
||||
saveToDisk(SEGMENT_CONFIG);
|
||||
}
|
||||
@@ -1124,6 +1112,7 @@ void NodeDB::loadFromDisk()
|
||||
&meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
if (state != LoadFileResult::LOAD_SUCCESS) {
|
||||
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
|
||||
restorePreferences(meshtastic_AdminMessage_BackupLocation_FLASH, SEGMENT_MODULECONFIG);
|
||||
} else {
|
||||
if (moduleConfig.version < DEVICESTATE_MIN_VER) {
|
||||
LOG_WARN("moduleConfig %d is old, discard", moduleConfig.version);
|
||||
@@ -1137,6 +1126,7 @@ void NodeDB::loadFromDisk()
|
||||
&channelFile);
|
||||
if (state != LoadFileResult::LOAD_SUCCESS) {
|
||||
installDefaultChannels(); // Our in RAM copy might now be corrupt
|
||||
restorePreferences(meshtastic_AdminMessage_BackupLocation_FLASH, SEGMENT_CHANNELS);
|
||||
} else {
|
||||
if (channelFile.version < DEVICESTATE_MIN_VER) {
|
||||
LOG_WARN("channelFile %d is old, discard", channelFile.version);
|
||||
@@ -1252,8 +1242,18 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
config.has_network = true;
|
||||
config.has_bluetooth = true;
|
||||
config.has_security = true;
|
||||
LOG_DEBUG("Saving config version %d", config.version);
|
||||
|
||||
success &= saveProto(configFileName, meshtastic_LocalConfig_size, &meshtastic_LocalConfig_msg, &config);
|
||||
#ifndef ARCH_NRF52
|
||||
// First, remove the temp file if it exists
|
||||
spiLock->lock();
|
||||
std::string tempFileName = std::string(configFileName) + ".tmp";
|
||||
FSCom.remove(tempFileName.c_str());
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
size_t configSize;
|
||||
pb_get_encoded_size(&configSize, meshtastic_LocalConfig_fields, &config);
|
||||
success &= saveProto(configFileName, configSize, &meshtastic_LocalConfig_msg, &config);
|
||||
}
|
||||
|
||||
if (saveWhat & SEGMENT_MODULECONFIG) {
|
||||
@@ -1269,9 +1269,18 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
moduleConfig.has_ambient_lighting = true;
|
||||
moduleConfig.has_audio = true;
|
||||
moduleConfig.has_paxcounter = true;
|
||||
LOG_DEBUG("Saving moduleConfig version %d", moduleConfig.version);
|
||||
|
||||
success &=
|
||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
#ifndef ARCH_NRF52
|
||||
// First, remove the temp file if it exists
|
||||
spiLock->lock();
|
||||
std::string tempFileName = std::string(configFileName) + ".tmp";
|
||||
FSCom.remove(tempFileName.c_str());
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
size_t moduleConfigSize;
|
||||
pb_get_encoded_size(&moduleConfigSize, meshtastic_LocalModuleConfig_fields, &moduleConfig);
|
||||
success &= saveProto(moduleConfigFileName, moduleConfigSize, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
}
|
||||
|
||||
if (saveWhat & SEGMENT_CHANNELS) {
|
||||
@@ -1612,6 +1621,94 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
||||
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||
}
|
||||
|
||||
bool NodeDB::backupPreferences(meshtastic_AdminMessage_BackupLocation location)
|
||||
{
|
||||
bool success = false;
|
||||
lastBackupAttempt = millis();
|
||||
#ifdef FSCom
|
||||
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
|
||||
backup.version = DEVICESTATE_CUR_VER;
|
||||
backup.timestamp = getValidTime(RTCQuality::RTCQualityDevice, false);
|
||||
backup.has_config = true;
|
||||
backup.config = config;
|
||||
backup.has_module_config = true;
|
||||
backup.module_config = moduleConfig;
|
||||
backup.has_channels = true;
|
||||
backup.channels = channelFile;
|
||||
backup.has_owner = true;
|
||||
backup.owner = owner;
|
||||
|
||||
size_t backupSize;
|
||||
pb_get_encoded_size(&backupSize, meshtastic_BackupPreferences_fields, &backup);
|
||||
|
||||
spiLock->lock();
|
||||
FSCom.mkdir("/backups");
|
||||
spiLock->unlock();
|
||||
success = saveProto(backupFileName, backupSize, &meshtastic_BackupPreferences_msg, &backup);
|
||||
|
||||
if (success) {
|
||||
LOG_INFO("Saved backup preferences");
|
||||
} else {
|
||||
LOG_ERROR("Failed to save backup preferences to file");
|
||||
}
|
||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
}
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location, int restoreWhat)
|
||||
{
|
||||
bool success = false;
|
||||
#ifdef FSCom
|
||||
if (location == meshtastic_AdminMessage_BackupLocation_FLASH) {
|
||||
spiLock->lock();
|
||||
if (!FSCom.exists(backupFileName)) {
|
||||
spiLock->unlock();
|
||||
LOG_WARN("Could not restore. No backup file found");
|
||||
return false;
|
||||
} else {
|
||||
spiLock->unlock();
|
||||
}
|
||||
meshtastic_BackupPreferences backup = meshtastic_BackupPreferences_init_zero;
|
||||
success = loadProto(backupFileName, meshtastic_BackupPreferences_size, sizeof(meshtastic_BackupPreferences),
|
||||
&meshtastic_BackupPreferences_msg, &backup);
|
||||
if (success) {
|
||||
if (restoreWhat & SEGMENT_CONFIG) {
|
||||
config = backup.config;
|
||||
LOG_DEBUG("Restored config");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_MODULECONFIG) {
|
||||
moduleConfig = backup.module_config;
|
||||
LOG_DEBUG("Restored module config");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_DEVICESTATE) {
|
||||
devicestate.owner = backup.owner;
|
||||
LOG_DEBUG("Restored device state");
|
||||
}
|
||||
if (restoreWhat & SEGMENT_CHANNELS) {
|
||||
channelFile = backup.channels;
|
||||
LOG_DEBUG("Restored channels");
|
||||
}
|
||||
|
||||
success = saveToDisk(restoreWhat);
|
||||
if (success) {
|
||||
LOG_INFO("Restored preferences from backup");
|
||||
} else {
|
||||
LOG_ERROR("Failed to save restored preferences to flash");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Failed to restore preferences from backup file");
|
||||
}
|
||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
}
|
||||
return success;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Record an error that should be reported via analytics
|
||||
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
|
||||
{
|
||||
|
||||
+9
-4
@@ -48,6 +48,7 @@ static constexpr const char *configFileName = "/prefs/config.proto";
|
||||
static constexpr const char *uiconfigFileName = "/prefs/uiconfig.proto";
|
||||
static constexpr const char *moduleConfigFileName = "/prefs/module.proto";
|
||||
static constexpr const char *channelFileName = "/prefs/channels.proto";
|
||||
static constexpr const char *backupFileName = "/backups/backup.proto";
|
||||
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
uint32_t sinceLastSeen(const meshtastic_NodeInfoLite *n);
|
||||
@@ -98,12 +99,10 @@ class NodeDB
|
||||
/** Reinit radio config if needed, because either:
|
||||
* a) sometimes a buggy android app might send us bogus settings or
|
||||
* 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
|
||||
* @return true if the config was completely reset, in that case, we should send it back to the client
|
||||
*/
|
||||
bool resetRadioConfig(bool factory_reset = false, bool is_fresh_install = false);
|
||||
void resetRadioConfig(bool factory_reset = false);
|
||||
|
||||
/// 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
|
||||
@@ -202,8 +201,14 @@ class NodeDB
|
||||
|
||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||
|
||||
// bool shouldAutoPerformBackup();
|
||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
int restoreWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
|
||||
private:
|
||||
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
|
||||
/// Find a node in our DB, create an empty NodeInfoLite if missing
|
||||
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
|
||||
|
||||
|
||||
@@ -370,6 +370,37 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
||||
LOG_DEBUG("Failed to delete file");
|
||||
}
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_backup_preferences_tag: {
|
||||
LOG_INFO("Client requesting to backup preferences");
|
||||
if (nodeDB->backupPreferences(r->backup_preferences)) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
} else {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_restore_preferences_tag: {
|
||||
LOG_INFO("Client requesting to restore preferences");
|
||||
if (nodeDB->restorePreferences(r->backup_preferences,
|
||||
SEGMENT_DEVICESTATE | SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_CHANNELS)) {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
|
||||
LOG_DEBUG("Rebooting after successful restore of preferences");
|
||||
reboot(1000);
|
||||
disableBluetooth();
|
||||
} else {
|
||||
myReply = allocErrorResponse(meshtastic_Routing_Error_BAD_REQUEST, &mp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case meshtastic_AdminMessage_remove_backup_preferences_tag: {
|
||||
LOG_INFO("Client requesting to remove backup preferences");
|
||||
#ifdef FSCom
|
||||
spiLock->lock();
|
||||
FSCom.remove(backupFileName);
|
||||
spiLock->unlock();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user