From 493d7e33c6b116d177f8074d1dd0bb632365f587 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 8 Feb 2020 07:41:04 -0800 Subject: [PATCH] add the concept of a minimum version for saved settings files --- TODO.md | 8 +++++--- src/NodeDB.cpp | 12 +++++++++++- src/mesh.pb.c | 1 + src/mesh.pb.h | 21 +++++++++++++++++---- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/TODO.md b/TODO.md index 41d7c149..53275626 100644 --- a/TODO.md +++ b/TODO.md @@ -2,10 +2,10 @@ * have node info screen show real info (including distance and heading) * very occasionally send our position and user packet (if for nothing else so that other nodes update last_seen) -* make a screen for bluetooth not yet configured # Medium priority +* sent/received packets (especially if a node was just reset) have variant of zero sometimes - I think there is a bug (race-condtion?) in the radio send/rx path. * only BLE advertise for a short time after the screen is on and button pressed - to save power and prevent people for sniffing for our BT app. * use https://platformio.org/lib/show/1260/OneButton * make an about to sleep screen @@ -15,7 +15,6 @@ * add basic crypto - http://rweather.github.io/arduinolibs/crypto.html with speck https://www.airspayce.com/mikem/arduino/RadioHead/rf95_encrypted_client_8pde-example.html * override peekAtMessage so we can see any messages that pass through our node (even if not broadcast)? would that be useful? * sendToMesh can currently block for a long time, instead have it just queue a packet for a radio freertos thread -* fix the logo * How do avalanche beacons work? Could this do that as well? possibly by using beacon mode feature of the RF95? * use std::map in node db * first alpha release, article writeup @@ -44,6 +43,7 @@ But fixme, think about this and look for standard solutions - it will have probl # Pre-beta priority +* make a screen for bluetooth not yet configured * swap out speck for accelerated full AES https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/include/esp32/hwcrypto/aes.h * cope with nodes that have 0xff or 0x00 as the last byte of their mac * use variable length arduino Strings in protobufs (instead of current fixed buffers) @@ -62,6 +62,7 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w # Low priority +* We let anyone scan for us (FIXME, perhaps only allow that until we are paired with a phone and configured) * use two different env flags for ttgo vs lora32. https://docs.platformio.org/en/latest/ide/vscode.html#key-bindings * sim gps data for testing nodes that don't have hardware * have android provide position data for nodes that don't have gps @@ -108,4 +109,5 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w * switch to my gui layout manager * make basic gui. different screens: debug, one page for each user in the user db, last received text message * make button press cycle between screens -* save our node db on entry to sleep \ No newline at end of file +* save our node db on entry to sleep +* fix the logo \ No newline at end of file diff --git a/src/NodeDB.cpp b/src/NodeDB.cpp index 73853c67..d0d393dd 100644 --- a/src/NodeDB.cpp +++ b/src/NodeDB.cpp @@ -92,17 +92,26 @@ const char *preftmp = "/db.proto.tmp"; void NodeDB::loadFromDisk() { + static DeviceState scratch; + File f = FS.open(preffile); if (f) { DEBUG_MSG("Loading saved preferences\n"); pb_istream_t stream = {&readcb, &f, DeviceState_size}; - if (!pb_decode(&stream, DeviceState_fields, &devicestate)) + scratch = DeviceState_init_zero; + if (!pb_decode(&stream, DeviceState_fields, &scratch)) { DEBUG_MSG("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream)); // FIXME - report failure to phone } + else { + if(scratch.version < DeviceState_Version_Minimum) + DEBUG_MSG("Warn: devicestate is old, discarding\n"); + else + devicestate = scratch; + } f.close(); } @@ -120,6 +129,7 @@ void NodeDB::saveToDisk() DEBUG_MSG("Writing preferences\n"); pb_ostream_t stream = {&writecb, &f, DeviceState_size, 0}; + devicestate.version = DeviceState_Version_Current; if (!pb_encode(&stream, DeviceState_fields, &devicestate)) { DEBUG_MSG("Error: can't write protobuf %s\n", PB_GET_ERROR(&stream)); diff --git a/src/mesh.pb.c b/src/mesh.pb.c index 3e8cb62b..9c1e5acc 100644 --- a/src/mesh.pb.c +++ b/src/mesh.pb.c @@ -48,6 +48,7 @@ PB_BIND(ToRadio, ToRadio, AUTO) + #ifndef PB_CONVERT_DOUBLE_FLOAT /* On some platforms (such as AVR), double is really float. * To be able to encode/decode double on these platforms, you need. diff --git a/src/mesh.pb.h b/src/mesh.pb.h index b671c620..cd357e50 100644 --- a/src/mesh.pb.h +++ b/src/mesh.pb.h @@ -27,6 +27,12 @@ typedef enum _RadioConfig_ModemConfig { RadioConfig_ModemConfig_Bw125Cr48Sf4096 = 3 } RadioConfig_ModemConfig; +typedef enum _DeviceState_Version { + DeviceState_Version_Unset = 0, + DeviceState_Version_Minimum = 1, + DeviceState_Version_Current = 1 +} DeviceState_Version; + /* Struct definitions */ typedef PB_BYTES_ARRAY_T(100) Data_payload_t; typedef struct _Data { @@ -114,6 +120,7 @@ typedef struct _DeviceState { NodeInfo node_db[32]; pb_size_t receive_queue_count; MeshPacket receive_queue[32]; + DeviceState_Version version; } DeviceState; typedef struct _FromRadio { @@ -141,6 +148,10 @@ typedef struct _ToRadio { #define _RadioConfig_ModemConfig_MAX RadioConfig_ModemConfig_Bw125Cr48Sf4096 #define _RadioConfig_ModemConfig_ARRAYSIZE ((RadioConfig_ModemConfig)(RadioConfig_ModemConfig_Bw125Cr48Sf4096+1)) +#define _DeviceState_Version_MIN DeviceState_Version_Unset +#define _DeviceState_Version_MAX DeviceState_Version_Current +#define _DeviceState_Version_ARRAYSIZE ((DeviceState_Version)(DeviceState_Version_Current+1)) + /* Initializer values for message structs */ #define Position_init_default {0, 0, 0, 0, 0} @@ -153,7 +164,7 @@ typedef struct _ToRadio { #define RadioConfig_init_default {0, 0, 0, 0, _RadioConfig_ModemConfig_MIN, {0, {0}}, 0, 0} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0} -#define DeviceState_init_default {false, RadioConfig_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, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}} +#define DeviceState_init_default {false, RadioConfig_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, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default, MeshPacket_init_default}, _DeviceState_Version_MIN} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} #define Position_init_zero {0, 0, 0, 0, 0} @@ -166,7 +177,7 @@ typedef struct _ToRadio { #define RadioConfig_init_zero {0, 0, 0, 0, _RadioConfig_ModemConfig_MIN, {0, {0}}, 0, 0} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0} -#define DeviceState_init_zero {false, RadioConfig_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, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}} +#define DeviceState_init_zero {false, RadioConfig_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, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero, MeshPacket_init_zero}, _DeviceState_Version_MIN} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} @@ -213,6 +224,7 @@ typedef struct _ToRadio { #define DeviceState_owner_tag 3 #define DeviceState_node_db_tag 4 #define DeviceState_receive_queue_tag 5 +#define DeviceState_version_tag 6 #define FromRadio_packet_tag 2 #define FromRadio_num_tag 1 #define ToRadio_packet_tag 1 @@ -308,7 +320,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, radio, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \ X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \ X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \ -X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) +X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \ +X(a, STATIC, SINGULAR, UENUM, version, 6) #define DeviceState_CALLBACK NULL #define DeviceState_DEFAULT NULL #define DeviceState_radio_MSGTYPE RadioConfig @@ -370,7 +383,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define RadioConfig_size 70 #define NodeInfo_size 151 #define MyNodeInfo_size 11 -#define DeviceState_size 9343 +#define DeviceState_size 9345 #define FromRadio_size 139 #define ToRadio_size 133