show real received text messages in the gui

This commit is contained in:
geeksville 2020-02-12 19:58:44 -08:00
parent 56f884cd10
commit 59aaffa3e5
7 changed files with 107 additions and 62 deletions

View File

@ -2,10 +2,10 @@
* have node info screen show real info (including distance and heading) * have node info screen show real info (including distance and heading)
* make debug info screen show real data (including battery level & charging) * make debug info screen show real data (including battery level & charging)
* show real text info on the text screen
* update build to generate both board types * update build to generate both board types
* retest BLE software update for both board types * retest BLE software update for both board types
* turn on screen when a new update arrives * turn on screen when a new update arrives
* don't forward redundent pings or ping responses to the phone, it just wastes phone battery
# Medium priority # Medium priority
@ -129,3 +129,4 @@ until the phone pulls those packets. Ever so often power on bluetooth just so w
* send location (or if not available user) when the user wakes the device from display sleep (both for testing and to improve user experience) * send location (or if not available user) when the user wakes the device from display sleep (both for testing and to improve user experience)
* make real implementation of getNumOnlineNodes * make real implementation of getNumOnlineNodes
* very occasionally send our position and user packet based on the schedule in the radio info (if for nothing else so that other nodes update last_seen) * very occasionally send our position and user packet based on the schedule in the radio info (if for nothing else so that other nodes update last_seen)
* show real text info on the text screen

View File

@ -75,6 +75,52 @@ void MeshService::sendOurOwner(NodeNum dest)
sendToMesh(p); sendToMesh(p);
} }
/// handle a user packet that just arrived on the radio, return NULL if we should not process this packet at all
MeshPacket *MeshService::handleFromRadioUser(MeshPacket *mp)
{
bool wasBroadcast = mp->to == NODENUM_BROADCAST;
bool isCollision = mp->from == myNodeInfo.my_node_num;
// we win if we have a lower macaddr
bool weWin = memcmp(&owner.macaddr, &mp->payload.variant.user.macaddr, sizeof(owner.macaddr)) < 0;
if (isCollision)
{
if (weWin)
{
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
packetPool.release(mp); // discard it
mp = NULL;
sendOurOwner(); // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
}
else
{
// we lost, we need to try for a new nodenum!
DEBUG_MSG("NOTE! Received a nodenum collision we lost, so picking a new nodenum\n");
nodeDB.updateFrom(*mp); // update the DB early - before trying to repick (so we don't select the same node number again)
nodeDB.pickNewNodeNum();
sendOurOwner(); // broadcast our new attempt at a node number
}
}
else if (wasBroadcast)
{
// If we haven't yet abandoned the packet and it was a broadcast, reply (just to them) with our User record so they can build their DB
// Someone just sent us a User, reply with our Owner
DEBUG_MSG("Received broadcast Owner from 0x%x, replying with our owner\n", mp->from);
sendOurOwner(mp->from);
String lcd = String("Joined: ") + mp->payload.variant.user.long_name + "\n";
screen_print(lcd.c_str());
}
return mp;
}
void MeshService::handleFromRadio() void MeshService::handleFromRadio()
{ {
MeshPacket *mp; MeshPacket *mp;
@ -82,47 +128,10 @@ void MeshService::handleFromRadio()
while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL)
{ {
mp->rx_time = gps.getTime() / 1000; // store the arrival timestamp for the phone mp->rx_time = gps.getTime() / 1000; // store the arrival timestamp for the phone
if (mp->has_payload && mp->payload.which_variant == SubPacket_user_tag) if (mp->has_payload && mp->payload.which_variant == SubPacket_user_tag)
{ {
bool wasBroadcast = mp->to == NODENUM_BROADCAST; mp = handleFromRadioUser(mp);
bool isCollision = mp->from == myNodeInfo.my_node_num;
// we win if we have a lower macaddr
bool weWin = memcmp(&owner.macaddr, &mp->payload.variant.user.macaddr, sizeof(owner.macaddr)) < 0;
if (isCollision)
{
if (weWin)
{
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
packetPool.release(mp); // discard it
mp = NULL;
sendOurOwner(); // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
}
else
{
// we lost, we need to try for a new nodenum!
DEBUG_MSG("NOTE! Received a nodenum collision we lost, so picking a new nodenum\n");
nodeDB.updateFrom(*mp); // update the DB early - before trying to repick (so we don't select the same node number again)
nodeDB.pickNewNodeNum();
sendOurOwner(); // broadcast our new attempt at a node number
}
}
else if (wasBroadcast)
{
// If we haven't yet abandoned the packet and it was a broadcast, reply (just to them) with our User record so they can build their DB
// Someone just sent us a User, reply with our Owner
DEBUG_MSG("Received broadcast Owner from 0x%x, replying with our owner\n", mp->from);
sendOurOwner(mp->from);
String lcd = String("Joined: ") + mp->payload.variant.user.long_name + "\n";
screen_print(lcd.c_str());
}
} }
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it) // If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
@ -206,6 +215,7 @@ MeshPacket *MeshService::allocForSending()
p->has_payload = true; p->has_payload = true;
p->from = nodeDB.getNodeNum(); p->from = nodeDB.getNodeNum();
p->to = NODENUM_BROADCAST; p->to = NODENUM_BROADCAST;
p->rx_time = gps.getTime() / 1000; // Just in case we process the packet locally - make sure it has a valid timestamp
return p; return p;
} }

View File

@ -80,6 +80,9 @@ private:
/// handle packets that just arrived from the mesh radio /// handle packets that just arrived from the mesh radio
void handleFromRadio(); void handleFromRadio();
/// handle a user packet that just arrived on the radio, return NULL if we should not process this packet at all
MeshPacket *handleFromRadioUser(MeshPacket *mp);
}; };
extern MeshService service; extern MeshService service;

View File

@ -236,7 +236,8 @@ void NodeDB::updateFrom(const MeshPacket &mp)
if (oldNumNodes != *numNodes) if (oldNumNodes != *numNodes)
updateGUI = true; // we just created a nodeinfo updateGUI = true; // we just created a nodeinfo
info->last_seen = gps.getTime() / 1000; // we keep time in seconds, not msecs if(mp.rx_time) // if the packet has a valid timestamp use it
info->last_seen = mp.rx_time;
switch (p.which_variant) switch (p.which_variant)
{ {
@ -246,6 +247,16 @@ void NodeDB::updateFrom(const MeshPacket &mp)
updateGUIforNode = info; updateGUIforNode = info;
break; break;
case SubPacket_data_tag: {
// Keep a copy of the most recent text message.
if(p.variant.data.typ == Data_Type_CLEAR_TEXT) {
devicestate.rx_text_message = mp;
devicestate.has_rx_text_message = true;
updateTextMessage = true;
}
break;
}
case SubPacket_user_tag: case SubPacket_user_tag:
{ {
DEBUG_MSG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name); DEBUG_MSG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
@ -255,11 +266,12 @@ void NodeDB::updateFrom(const MeshPacket &mp)
info->user = p.variant.user; info->user = p.variant.user;
DEBUG_MSG("updating changed=%d user %s/%s/%s\n", changed, info->user.id, info->user.long_name, info->user.short_name); DEBUG_MSG("updating changed=%d user %s/%s/%s\n", changed, info->user.id, info->user.long_name, info->user.short_name);
info->has_user = true; info->has_user = true;
updateGUIforNode = info;
if (changed) if (changed)
{ {
// We just created a user for the first time, store our DB updateGUIforNode = info;
// We just changed something important about the user, store our DB
saveToDisk(); saveToDisk();
} }
break; break;

View File

@ -6,6 +6,7 @@
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include "MeshTypes.h" #include "MeshTypes.h"
extern DeviceState devicestate;
extern MyNodeInfo &myNodeInfo; extern MyNodeInfo &myNodeInfo;
extern RadioConfig &radioConfig; extern RadioConfig &radioConfig;
extern ChannelSettings &channelSettings; extern ChannelSettings &channelSettings;
@ -25,12 +26,13 @@ class NodeDB
NodeInfo *nodes; NodeInfo *nodes;
pb_size_t *numNodes; pb_size_t *numNodes;
bool updateGUI = false; // we think the gui should definitely be redrawn
NodeInfo *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
int readPointer = 0; int readPointer = 0;
public: public:
bool updateGUI = false; // we think the gui should definitely be redrawn, screen will clear this once handled
NodeInfo *updateGUIforNode = NULL; // if currently showing this node, we think you should update the GUI
bool updateTextMessage = false; // if true, the GUI should show a new text message
/// don't do mesh based algoritm for node id assignment (initially) /// don't do mesh based algoritm for node id assignment (initially)
/// instead just store in flash - possibly even in the initial alpha release do this hack /// instead just store in flash - possibly even in the initial alpha release do this hack
NodeDB(); NodeDB();

View File

@ -127,6 +127,8 @@ typedef struct _DeviceState {
pb_size_t receive_queue_count; pb_size_t receive_queue_count;
MeshPacket receive_queue[32]; MeshPacket receive_queue[32];
DeviceState_Version version; DeviceState_Version version;
bool has_rx_text_message;
MeshPacket rx_text_message;
} DeviceState; } DeviceState;
typedef struct _FromRadio { typedef struct _FromRadio {
@ -174,7 +176,7 @@ typedef struct _ToRadio {
#define RadioConfig_UserPreferences_init_default {0, 0, 0, 0} #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0}
#define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, 0} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0, 0}
#define MyNodeInfo_init_default {0, 0} #define MyNodeInfo_init_default {0, 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}, _DeviceState_Version_MIN} #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, false, MeshPacket_init_default}
#define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}}
#define ToRadio_init_default {0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}}
#define Position_init_zero {0, 0, 0, 0, 0} #define Position_init_zero {0, 0, 0, 0, 0}
@ -187,7 +189,7 @@ typedef struct _ToRadio {
#define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0} #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0}
#define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, 0} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0, 0}
#define MyNodeInfo_init_zero {0, 0} #define MyNodeInfo_init_zero {0, 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}, _DeviceState_Version_MIN} #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, false, MeshPacket_init_zero}
#define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}}
#define ToRadio_init_zero {0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}}
@ -235,6 +237,7 @@ typedef struct _ToRadio {
#define DeviceState_node_db_tag 4 #define DeviceState_node_db_tag 4
#define DeviceState_receive_queue_tag 5 #define DeviceState_receive_queue_tag 5
#define DeviceState_version_tag 6 #define DeviceState_version_tag 6
#define DeviceState_rx_text_message_tag 7
#define FromRadio_packet_tag 2 #define FromRadio_packet_tag 2
#define FromRadio_num_tag 1 #define FromRadio_num_tag 1
#define ToRadio_packet_tag 1 #define ToRadio_packet_tag 1
@ -331,7 +334,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, my_node, 2) \
X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \ X(a, STATIC, OPTIONAL, MESSAGE, owner, 3) \
X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \ 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) X(a, STATIC, SINGULAR, UENUM, version, 6) \
X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7)
#define DeviceState_CALLBACK NULL #define DeviceState_CALLBACK NULL
#define DeviceState_DEFAULT NULL #define DeviceState_DEFAULT NULL
#define DeviceState_radio_MSGTYPE RadioConfig #define DeviceState_radio_MSGTYPE RadioConfig
@ -339,6 +343,7 @@ X(a, STATIC, SINGULAR, UENUM, version, 6)
#define DeviceState_owner_MSGTYPE User #define DeviceState_owner_MSGTYPE User
#define DeviceState_node_db_MSGTYPE NodeInfo #define DeviceState_node_db_MSGTYPE NodeInfo
#define DeviceState_receive_queue_MSGTYPE MeshPacket #define DeviceState_receive_queue_MSGTYPE MeshPacket
#define DeviceState_rx_text_message_MSGTYPE MeshPacket
#define FromRadio_FIELDLIST(X, a) \ #define FromRadio_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, num, 1) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \
@ -393,7 +398,7 @@ extern const pb_msgdesc_t ToRadio_msg;
#define RadioConfig_UserPreferences_size 18 #define RadioConfig_UserPreferences_size 18
#define NodeInfo_size 157 #define NodeInfo_size 157
#define MyNodeInfo_size 13 #define MyNodeInfo_size 13
#define DeviceState_size 13029 #define DeviceState_size 13271
#define FromRadio_size 248 #define FromRadio_size 248
#define ToRadio_size 242 #define ToRadio_size 242

View File

@ -129,15 +129,22 @@ void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int1
/// Draw the last text message we received /// Draw the last text message we received
void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
MeshPacket &mp = devicestate.rx_text_message;
NodeInfo *node = nodeDB.getNode(mp.from);
// Demo for drawStringMaxWidth: // Demo for drawStringMaxWidth:
// with the third parameter you can define the width after which words will be wrapped. // with the third parameter you can define the width after which words will be wrapped.
// Currently only spaces and "-" are allowed for wrapping // Currently only spaces and "-" are allowed for wrapping
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_16); display->setFont(ArialMT_Plain_16);
String sender = "KH:"; String sender = (node && node->has_user) ? node->user.short_name : "???";
display->drawString(0 + x, 0 + y, sender); display->drawString(0 + x, 0 + y, sender);
display->setFont(ArialMT_Plain_10); display->setFont(ArialMT_Plain_10);
display->drawStringMaxWidth(4 + x, 10 + y, 128, " Hey - I found the trail, but I've fallen and I can't get up. ;-)");
static char tempBuf[96];
snprintf(tempBuf, sizeof(tempBuf), " %s", mp.payload.variant.data.payload.bytes); // the max length of this buffer is much longer than we can possibly print
display->drawStringMaxWidth(4 + x, 10 + y, 128, tempBuf);
// ui.disableIndicator(); // ui.disableIndicator();
} }
@ -495,11 +502,9 @@ uint32_t screen_loop()
else // standard screen loop handling ehre else // standard screen loop handling ehre
{ {
// If the # nodes changes, we need to regen our list of screens // If the # nodes changes, we need to regen our list of screens
static size_t oldnumnodes = 0; if (nodeDB.updateGUI)
size_t numnodes = nodeDB.getNumNodes();
if (numnodes != oldnumnodes)
{ {
oldnumnodes = numnodes; nodeDB.updateGUI = false;
screen_set_frames(); screen_set_frames();
} }
@ -536,18 +541,25 @@ void screen_set_frames()
{ {
DEBUG_MSG("showing standard frames\n"); DEBUG_MSG("showing standard frames\n");
nonBootFrames[0] = drawTextMessageFrame;
nonBootFrames[1] = drawDebugInfo;
size_t numnodes = nodeDB.getNumNodes(); size_t numnodes = nodeDB.getNumNodes();
// We don't show the node info our our node (if we have it yet - we should) // We don't show the node info our our node (if we have it yet - we should)
if (numnodes > 0) if (numnodes > 0)
numnodes--; numnodes--;
for (size_t i = 0; i < numnodes; i++) size_t numframes = 0;
nonBootFrames[NUM_EXTRA_FRAMES + i] = drawNodeInfo;
ui.setFrames(nonBootFrames, NUM_EXTRA_FRAMES + numnodes); // If we have a text message - show it first
if(devicestate.has_rx_text_message)
nonBootFrames[numframes++] = drawTextMessageFrame;
// then all the nodes
for (size_t i = 0; i < numnodes; i++)
nonBootFrames[numframes++] = drawNodeInfo;
// then the debug info
nonBootFrames[numframes++] = drawDebugInfo;
ui.setFrames(nonBootFrames, numframes);
showingBluetooth = false; showingBluetooth = false;
} }