diff --git a/proto b/proto index e6e1c5a60..5c1062ea8 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit e6e1c5a600147428af553304b47f25f21492965d +Subproject commit 5c1062ea839f97cfc6d33d428a89d1702c39bd93 diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index c4d58d4c3..7d8115878 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -128,7 +128,7 @@ void NodeDB::installDefaultRadioConfig() void NodeDB::installDefaultChannels() { - memset(&channelFile, 0, sizeof(channelFile)); + memset(&channelFile, 0, sizeof(channelFile)); } void NodeDB::installDefaultDeviceState() @@ -169,8 +169,8 @@ void NodeDB::installDefaultDeviceState() if (oldRegion.length()) // If the old style region was set, try to keep it up-to-date strcpy(myNodeInfo.region, oldRegion.c_str()); - installDefaultChannels(); - installDefaultRadioConfig(); + installDefaultChannels(); + installDefaultRadioConfig(); } void NodeDB::init() @@ -199,12 +199,16 @@ void NodeDB::init() info->user = owner; info->has_user = true; + // removed from 1.2 (though we do use old values if found) // We set these _after_ loading from disk - because they come from the build and are more trusted than // what is stored in flash - if (xstr(HW_VERSION)[0]) - strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); - else - DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag + //if (xstr(HW_VERSION)[0]) + // strncpy(myNodeInfo.region, optstr(HW_VERSION), sizeof(myNodeInfo.region)); + // else DEBUG_MSG("This build does not specify a HW_VERSION\n"); // Eventually new builds will no longer include this build flag + + // DEBUG_MSG("legacy region %d\n", devicestate.legacyRadio.preferences.region); + if(radioConfig.preferences.region == RegionCode_Unset) + radioConfig.preferences.region = devicestate.legacyRadio.preferences.region; // Check for the old style of region code strings, if found, convert to the new enum. // Those strings will look like "1.0-EU433" @@ -222,8 +226,7 @@ void NodeDB::init() resetRadioConfig(); // If bogus settings got saved, then fix them - DEBUG_MSG("legacy_region=%s, region=%d, NODENUM=0x%x, dbsize=%d\n", myNodeInfo.region, radioConfig.preferences.region, - myNodeInfo.my_node_num, *numNodes); + DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", radioConfig.preferences.region, myNodeInfo.my_node_num, *numNodes); } // We reserve a few nodenums for future use @@ -253,9 +256,10 @@ void NodeDB::pickNewNodeNum() myNodeInfo.my_node_num = r; } -const char *preffile = "/db.proto"; -const char *radiofile = "/radio.proto"; -const char *channelfile = "/channels.proto"; +static const char *preffileOld = "/db.proto"; +static const char *preffile = "/prefs/db.proto"; +static const char *radiofile = "/prefs/radio.proto"; +static const char *channelfile = "/prefs/channels.proto"; // const char *preftmp = "/db.proto.tmp"; /** Load a protobuf from a file, return true for success */ @@ -265,6 +269,14 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_ // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM auto f = FS.open(filename); + + // FIXME, temporary hack until every node in the universe is 1.2 or later - look for prefs in the old location (so we can + // preserve region) + if (!f && filename == preffile) { + filename = preffileOld; + f = FS.open(filename); + } + bool okay = false; if (f) { DEBUG_MSG("Loading %s\n", filename); @@ -281,9 +293,8 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_ f.close(); } else { - DEBUG_MSG("No saved preferences found\n"); + DEBUG_MSG("No %s preferences found\n", filename); } - #else DEBUG_MSG("ERROR: Filesystem not implemented\n"); #endif @@ -309,47 +320,60 @@ void NodeDB::loadFromDisk() } if (!loadProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) { - installDefaultRadioConfig(); // Our in RAM copy might now be corrupt - } + installDefaultChannels(); // Our in RAM copy might now be corrupt + } +} + +/** Save a protobuf from a file, return true for success */ +bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct) +{ +#ifdef FS + // static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM + String filenameTmp = filename; + filenameTmp += ".tmp"; + auto f = FS.open(filenameTmp.c_str(), FILE_O_WRITE); + bool okay = false; + if (f) { + DEBUG_MSG("Saving %s\n", filename); + pb_ostream_t stream = {&writecb, &f, protoSize}; + + if (!pb_encode(&stream, fields, dest_struct)) { + DEBUG_MSG("Error: can't encode protobuf %s\n", PB_GET_ERROR(&stream)); + } else { + okay = true; + } + + f.close(); + + // brief window of risk here ;-) + if (!FS.remove(filename)) + DEBUG_MSG("Warning: Can't remove old pref file\n"); + if (!FS.rename(filenameTmp.c_str(), filename)) + DEBUG_MSG("Error: can't rename new pref file\n"); + } else { + DEBUG_MSG("Can't write prefs\n"); + } +#else + DEBUG_MSG("ERROR: Filesystem not implemented\n"); +#endif + return okay; } void NodeDB::saveToDisk() { -#ifdef FS if (!devicestate.no_save) { - auto f = FS.open(preftmp, FILE_O_WRITE); - if (f) { - DEBUG_MSG("Writing preferences\n"); +#ifdef FS + FS.mkdir("/prefs"); +#endif + bool okay = saveProto(preffile, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate); + okay &= saveProto(radiofile, RadioConfig_size, sizeof(RadioConfig), RadioConfig_fields, &radioConfig); + okay &= saveProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile); - pb_ostream_t stream = {&writecb, &f, SIZE_MAX, 0}; - - // DEBUG_MSG("Presave channel name=%s\n", channelSettings.name); - - devicestate.version = DEVICESTATE_CUR_VER; - if (!pb_encode(&stream, DeviceState_fields, &devicestate)) { - DEBUG_MSG("Error: can't write protobuf %s\n", PB_GET_ERROR(&stream)); - // FIXME - report failure to phone - - f.close(); - } else { - // Success - replace the old file - f.close(); - - // brief window of risk here ;-) - if (!FS.remove(preffile)) - DEBUG_MSG("Warning: Can't remove old pref file\n"); - if (!FS.rename(preftmp, preffile)) - DEBUG_MSG("Error: can't rename new pref file\n"); - } - } else { - DEBUG_MSG("ERROR: can't write prefs\n"); // FIXME report to app - } + // remove any pre 1.2 pref files, turn on after 1.2 is in beta + // if(okay) FS.remove(preffileOld); } else { DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n"); } -#else - DEBUG_MSG("ERROR filesystem not implemented\n"); -#endif } const NodeInfo *NodeDB::readNextInfo() diff --git a/src/mesh/generated/deviceonly.pb.c b/src/mesh/generated/deviceonly.pb.c index 39e044580..dd2bb751f 100644 --- a/src/mesh/generated/deviceonly.pb.c +++ b/src/mesh/generated/deviceonly.pb.c @@ -6,6 +6,12 @@ #error Regenerate this file with the current version of nanopb generator. #endif +PB_BIND(LegacyRadioConfig, LegacyRadioConfig, AUTO) + + +PB_BIND(LegacyRadioConfig_LegacyPreferences, LegacyRadioConfig_LegacyPreferences, AUTO) + + PB_BIND(DeviceState, DeviceState, 2) diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index c4a498248..9c40e2110 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -6,6 +6,7 @@ #include #include "mesh.pb.h" #include "channel.pb.h" +#include "radioconfig.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. @@ -17,7 +18,18 @@ typedef struct _ChannelFile { Channel channels[8]; } ChannelFile; +typedef struct _LegacyRadioConfig_LegacyPreferences { + RegionCode region; +} LegacyRadioConfig_LegacyPreferences; + +typedef struct _LegacyRadioConfig { + bool has_preferences; + LegacyRadioConfig_LegacyPreferences preferences; +} LegacyRadioConfig; + typedef struct _DeviceState { + bool has_legacyRadio; + LegacyRadioConfig legacyRadio; bool has_my_node; MyNodeInfo my_node; bool has_owner; @@ -39,13 +51,20 @@ extern "C" { #endif /* Initializer values for message structs */ -#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} +#define LegacyRadioConfig_init_default {false, LegacyRadioConfig_LegacyPreferences_init_default} +#define LegacyRadioConfig_LegacyPreferences_init_default {_RegionCode_MIN} +#define DeviceState_init_default {false, LegacyRadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} #define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}} -#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} +#define LegacyRadioConfig_init_zero {false, LegacyRadioConfig_LegacyPreferences_init_zero} +#define LegacyRadioConfig_LegacyPreferences_init_zero {_RegionCode_MIN} +#define DeviceState_init_zero {false, LegacyRadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} #define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define ChannelFile_channels_tag 1 +#define LegacyRadioConfig_LegacyPreferences_region_tag 15 +#define LegacyRadioConfig_preferences_tag 1 +#define DeviceState_legacyRadio_tag 1 #define DeviceState_my_node_tag 2 #define DeviceState_owner_tag 3 #define DeviceState_node_db_tag 4 @@ -56,7 +75,19 @@ extern "C" { #define DeviceState_did_gps_reset_tag 11 /* Struct field encoding specification for nanopb */ +#define LegacyRadioConfig_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, preferences, 1) +#define LegacyRadioConfig_CALLBACK NULL +#define LegacyRadioConfig_DEFAULT NULL +#define LegacyRadioConfig_preferences_MSGTYPE LegacyRadioConfig_LegacyPreferences + +#define LegacyRadioConfig_LegacyPreferences_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, region, 15) +#define LegacyRadioConfig_LegacyPreferences_CALLBACK NULL +#define LegacyRadioConfig_LegacyPreferences_DEFAULT NULL + #define DeviceState_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, legacyRadio, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \ X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \ @@ -67,6 +98,7 @@ X(a, STATIC, SINGULAR, BOOL, no_save, 9) \ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11) #define DeviceState_CALLBACK NULL #define DeviceState_DEFAULT NULL +#define DeviceState_legacyRadio_MSGTYPE LegacyRadioConfig #define DeviceState_my_node_MSGTYPE MyNodeInfo #define DeviceState_owner_MSGTYPE User #define DeviceState_node_db_MSGTYPE NodeInfo @@ -79,15 +111,21 @@ X(a, STATIC, REPEATED, MESSAGE, channels, 1) #define ChannelFile_DEFAULT NULL #define ChannelFile_channels_MSGTYPE Channel +extern const pb_msgdesc_t LegacyRadioConfig_msg; +extern const pb_msgdesc_t LegacyRadioConfig_LegacyPreferences_msg; extern const pb_msgdesc_t DeviceState_msg; extern const pb_msgdesc_t ChannelFile_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define LegacyRadioConfig_fields &LegacyRadioConfig_msg +#define LegacyRadioConfig_LegacyPreferences_fields &LegacyRadioConfig_LegacyPreferences_msg #define DeviceState_fields &DeviceState_msg #define ChannelFile_fields &ChannelFile_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 5050 +#define LegacyRadioConfig_size 4 +#define LegacyRadioConfig_LegacyPreferences_size 2 +#define DeviceState_size 5056 #define ChannelFile_size 832 #ifdef __cplusplus