diff --git a/docs/software/TODO.md b/docs/software/TODO.md
index e879c5779e0a333b9b2bfc0ae69e344edd4d2e46..2633d3bcfbcf7b4330f8bf5c419c71aac8424ac0 100644
--- a/docs/software/TODO.md
+++ b/docs/software/TODO.md
@@ -4,12 +4,15 @@ You probably don't care about this section - skip to the next one.
 
 ## before next release
 
-* TEST THIS! changing channels requires a reboot to take effect https://github.com/meshtastic/Meshtastic-device/issues/752 
-* add UI in android app to reset to defaults https://github.com/meshtastic/Meshtastic-Android/issues/263 
-* bug report with remote info request timing out
-* firmware OTA updates of is_router true nodes fails?
-* move remote admin doc from forum into git
-* ask for a documentation czar
+* DONE test latest firmware update with is_router
+* DONE firmware OTA updates of is_router true nodes fails?
+* DONE add UI in android app to reset to defaults https://github.com/meshtastic/Meshtastic-Android/issues/263 
+* DONE TEST THIS! changing channels requires a reboot to take effect https://github.com/meshtastic/Meshtastic-device/issues/752 
+* DIBE bug report with remote info request timing out
+* DONE retest channel changing in android (using sim?)
+* DONE move remote admin doc from forum into git
+* DONE check crashlytics
+* DONE ask for a documentation czar
 * DONE timestamps on oled screen are wrong - don't seem to be updating based on message rx (actually: this is expected behavior when no node on the mesh has GPS time)
 * DONE add ch-del
 * DONE channel hash suffixes are wrong on android
diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp
index 1303329e53d09d2d7c1cdfe7086d321189c49069..86bc916394656a744c377a3be2a3bccc53ee0a1f 100644
--- a/src/PowerFSM.cpp
+++ b/src/PowerFSM.cpp
@@ -97,7 +97,8 @@ static void lsIdle()
 static void lsExit()
 {
     // setGPSPower(true); // restore GPS power
-    if (gps) gps->forceWake(true);
+    if (gps)
+        gps->forceWake(true);
 }
 
 static void nbEnter()
@@ -172,7 +173,7 @@ Fsm powerFSM(&stateBOOT);
 void PowerFSM_setup()
 {
     bool isRouter = radioConfig.preferences.is_router;
-        
+
     // If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
     // We assume routers might be powered all the time, but from a low current (solar) source
     bool isLowPower = radioConfig.preferences.is_low_power || isRouter;
@@ -180,7 +181,7 @@ void PowerFSM_setup()
     /* To determine if we're externally powered, assumptions
         1) If we're powered up and there's no battery, we must be getting power externally. (because we'd be dead otherwise)
 
-        2) If we detect USB power from the power management chip, we must be getting power externally. 
+        2) If we detect USB power from the power management chip, we must be getting power externally.
     */
     bool hasPower = !isLowPower && powerStatus && (!powerStatus->getHasBattery() || powerStatus->getHasUSB());
 
@@ -249,6 +250,11 @@ void PowerFSM_setup()
 
     powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
 
+    // each time we get a new update packet make sure we are staying in the ON state so the screen stays awake (also we don't
+    // shutdown bluetooth if is_router)
+    powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
+    powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
+
     powerFSM.add_transition(&stateNB, &stateDARK, EVENT_PACKET_FOR_PHONE, NULL, "Packet for phone");
 
     powerFSM.add_timed_transition(&stateON, &stateDARK, getPref_screen_on_secs() * 1000, NULL, "Screen-on timeout");
diff --git a/src/PowerFSM.h b/src/PowerFSM.h
index 4af62040ca3e28f8e08d9b6d7eacfb6ef7f1923a..e48b55d8793b555556fc860f40c9bd5e72ca8be7 100644
--- a/src/PowerFSM.h
+++ b/src/PowerFSM.h
@@ -18,6 +18,7 @@
 #define EVENT_SERIAL_DISCONNECTED 12
 #define EVENT_POWER_CONNECTED 13
 #define EVENT_POWER_DISCONNECTED 14
+#define EVENT_FIRMWARE_UPDATE 15 // We just received a new firmware update packet from the phone
 
 extern Fsm powerFSM;
 extern State statePOWER, stateSERIAL;
diff --git a/src/esp32/BluetoothSoftwareUpdate.cpp b/src/esp32/BluetoothSoftwareUpdate.cpp
index 33707c57a12f2005d6c1450dc8b02097f3048519..843b14cf61636ea61f14c644fd9e67df947e1df3 100644
--- a/src/esp32/BluetoothSoftwareUpdate.cpp
+++ b/src/esp32/BluetoothSoftwareUpdate.cpp
@@ -1,14 +1,14 @@
 #include <Arduino.h>
 
 #include "../concurrency/LockGuard.h"
+#include "../graphics/Screen.h"
+#include "../main.h"
 #include "BluetoothSoftwareUpdate.h"
+#include "NodeDB.h"
 #include "PowerFSM.h"
 #include "RadioLibInterface.h"
 #include "configuration.h"
 #include "nimble/BluetoothUtil.h"
-#include "NodeDB.h"
-#include "../graphics/Screen.h"
-#include "../main.h"
 
 #include <CRC32.h>
 #include <Update.h>
@@ -51,8 +51,8 @@ int update_size_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_
 
             screen->startFirmwareUpdateScreen();
             if (RadioLibInterface::instance)
-                RadioLibInterface::instance->disable(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we are
-                                                      // writing flash - shut the radio off during updates
+                RadioLibInterface::instance->disable(); // FIXME, nasty hack - the RF95 ISR/SPI code on ESP32 can fail while we
+                                                        // are writing flash - shut the radio off during updates
         }
     }
 
@@ -78,7 +78,7 @@ int update_data_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble_
     crc.update(data, len);
     Update.write(data, len);
     updateActualSize += len;
-    powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);
+    powerFSM.trigger(EVENT_FIRMWARE_UPDATE);
 
     return 0;
 }
@@ -107,8 +107,7 @@ int update_crc32_callback(uint16_t conn_handle, uint16_t attr_handle, struct ble
             if (update_region == U_SPIFFS) {
                 DEBUG_MSG("SPIFFS updated!\n");
                 nodeDB.saveToDisk(); // Since we just wiped spiffs, we need to save our current state
-            }
-            else {
+            } else {
                 DEBUG_MSG("Appload updated, rebooting in 5 seconds!\n");
                 rebootAtMsec = millis() + 5000;
             }
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 37e1e9f02c437a5a2d0b2397496f47859dc51fa1..f925665e920d91a1e413b34bf0330ee46fe74a97 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -82,6 +82,7 @@ bool NodeDB::resetRadioConfig()
 
     radioGeneration++;
 
+    radioConfig.has_preferences = true;
     if (radioConfig.preferences.factory_reset) {
         DEBUG_MSG("Performing factory reset!\n");
         installDefaultDeviceState();
@@ -92,8 +93,6 @@ bool NodeDB::resetRadioConfig()
         DEBUG_MSG("Setting default channel and radio preferences!\n");
 
         channels.initDefaults();
-
-        radioConfig.has_preferences = true;
     }
 
     channels.onConfigChanged();
@@ -487,7 +486,7 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p)
 /// we updateGUI and updateGUIforNode if we think our this change is big enough for a redraw
 void NodeDB::updateFrom(const MeshPacket &mp)
 {
-    if (mp.which_payloadVariant == MeshPacket_decoded_tag) {
+    if (mp.which_payloadVariant == MeshPacket_decoded_tag && mp.from) {
         DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
 
         NodeInfo *info = getOrCreateNode(getFrom(&mp));
@@ -497,7 +496,8 @@ void NodeDB::updateFrom(const MeshPacket &mp)
             info->position.time = mp.rx_time;
         }
 
-        info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
+        if (mp.rx_snr)
+            info->snr = mp.rx_snr; // keep the most recent SNR we received for this node.
     }
 }
 
diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp
index 52b28eb559ea4d1ad5519952c9264fe4af32dd9a..fe207de1e842ab8a14c0e908343137a7c0ef1203 100644
--- a/src/mesh/Router.cpp
+++ b/src/mesh/Router.cpp
@@ -115,7 +115,8 @@ void Router::abortSendAndNak(Routing_Error err, MeshPacket *p)
     packetPool.release(p);
 }
 
-void Router::setReceivedMessage() {
+void Router::setReceivedMessage()
+{
     setInterval(0); // Run ASAP, so we can figure out our correct sleep time
 }
 
@@ -123,9 +124,13 @@ ErrorCode Router::sendLocal(MeshPacket *p)
 {
     // No need to deliver externally if the destination is the local node
     if (p->to == nodeDB.getNodeNum()) {
-        printPacket("Enqueuing local", p);
-        fromRadioQueue.enqueue(p);
-        setReceivedMessage();
+        if (fromRadioQueue.enqueue(p, 0)) {
+            printPacket("Enqueued local", p);
+            setReceivedMessage();
+        } else {
+            printPacket("BUG! fromRadioQueue is full! Discarding!", p);
+            packetPool.release(p);
+        }
         return ERRNO_OK;
     } else if (!iface) {
         // We must be sending to remote nodes also, fail if no interface found
@@ -143,9 +148,10 @@ ErrorCode Router::sendLocal(MeshPacket *p)
     }
 }
 
-void printBytes(const char *label, const uint8_t *p, size_t numbytes) {
+void printBytes(const char *label, const uint8_t *p, size_t numbytes)
+{
     DEBUG_MSG("%s: ", label);
-    for(size_t i = 0; i < numbytes; i++)
+    for (size_t i = 0; i < numbytes; i++)
         DEBUG_MSG("%02x ", p[i]);
     DEBUG_MSG("\n");
 }
@@ -189,7 +195,7 @@ ErrorCode Router::send(MeshPacket *p)
             return ERRNO_TOO_LARGE;
         }
 
-        //printBytes("plaintext", bytes, numbytes);
+        // printBytes("plaintext", bytes, numbytes);
 
         auto hash = channels.setActiveByIndex(p->channel);
         if (hash < 0) {
@@ -247,19 +253,18 @@ bool Router::perhapsDecode(MeshPacket *p)
                    rawSize); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf
             crypto->decrypt(p->from, p->id, rawSize, bytes);
 
-            //printBytes("plaintext", bytes, p->encrypted.size);            
+            // printBytes("plaintext", bytes, p->encrypted.size);
 
             // Take those raw bytes and convert them back into a well structured protobuf we can understand
-            memset(&p->decoded, 0, sizeof(p->decoded)); 
+            memset(&p->decoded, 0, sizeof(p->decoded));
             if (!pb_decode_from_bytes(bytes, rawSize, Data_fields, &p->decoded)) {
                 DEBUG_MSG("Invalid protobufs in received mesh packet (bad psk?)!\n");
-            } else if(p->decoded.portnum == PortNum_UNKNOWN_APP) {
+            } else if (p->decoded.portnum == PortNum_UNKNOWN_APP) {
                 DEBUG_MSG("Invalid portnum (bad psk?)!\n");
-            }
-            else {
+            } else {
                 // parsing was successful
                 p->which_payloadVariant = MeshPacket_decoded_tag; // change type to decoded
-                p->channel = chIndex; // change to store the index instead of the hash
+                p->channel = chIndex;                             // change to store the index instead of the hash
                 printPacket("decoded message", p);
                 return true;
             }
@@ -285,7 +290,7 @@ void Router::handleReceived(MeshPacket *p)
     p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
 
     // Take those raw bytes and convert them back into a well structured protobuf we can understand
-    bool decoded = perhapsDecode(p); 
+    bool decoded = perhapsDecode(p);
     if (decoded) {
         // parsing was successful, queue for our recipient
         printPacket("handleReceived", p);
@@ -293,18 +298,20 @@ void Router::handleReceived(MeshPacket *p)
         // call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api
         // sniffReceived(p);
         MeshPlugin::callPlugins(*p);
+    } else {
+        DEBUG_MSG("packet decoding failed\n");
     }
 }
 
 void Router::perhapsHandleReceived(MeshPacket *p)
 {
     assert(radioConfig.has_preferences);
-    bool ignore = is_in_repeated(radioConfig.preferences.ignore_incoming, getFrom(p));
+    bool ignore = is_in_repeated(radioConfig.preferences.ignore_incoming, p->from);
 
     if (ignore)
         DEBUG_MSG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from);
     else if (ignore |= shouldFilterReceived(p)) {
-        // DEBUG_MSG("Incoming message was filtered 0x%x\n", p->from);
+        DEBUG_MSG("Incoming message was filtered 0x%x\n", p->from);
     }
 
     // Note: we avoid calling shouldFilterReceived if we are supposed to ignore certain nodes - because some overrides might
diff --git a/src/mesh/TypedQueue.h b/src/mesh/TypedQueue.h
index 0b60e6cf74689574a98b2055c273bb7f1b6ab92d..09d828a9625c2be7c679c4274f01f11e535b820a 100644
--- a/src/mesh/TypedQueue.h
+++ b/src/mesh/TypedQueue.h
@@ -31,7 +31,9 @@ template <class T> class TypedQueue
 
     bool isEmpty() { return uxQueueMessagesWaiting(h) == 0; }
 
-    bool enqueue(T x, TickType_t maxWait = portMAX_DELAY)
+    /** euqueue a packet.  Also, maxWait used to default to portMAX_DELAY, but we now want to callers to THINK about what blocking
+     * they want */
+    bool enqueue(T x, TickType_t maxWait)
     {
         if (reader) {
             reader->setInterval(0);
diff --git a/src/plugins/esp32/StoreForwardPlugin.cpp b/src/plugins/esp32/StoreForwardPlugin.cpp
index e5694caa38e6fbb6cb29fefdaa0a674eef40bbff..8e068682542ad4d9d0e63ee25f422e5bc58db6af 100644
--- a/src/plugins/esp32/StoreForwardPlugin.cpp
+++ b/src/plugins/esp32/StoreForwardPlugin.cpp
@@ -280,9 +280,9 @@ StoreForwardPlugin::StoreForwardPlugin()
         Uncomment the preferences below if you want to use the plugin
         without having to configure it from the PythonAPI or WebUI.
 
-    */
     radioConfig.preferences.store_forward_plugin_enabled = 1;
     radioConfig.preferences.is_router = 1;
+    */
 
     if (radioConfig.preferences.store_forward_plugin_enabled) {
 
@@ -305,7 +305,7 @@ StoreForwardPlugin::StoreForwardPlugin()
                 DEBUG_MSG("Store & Forward Plugin - Aborting Startup.\n");
             }
 
-        // Client
+            // Client
         } else {
             DEBUG_MSG("Initializing Store & Forward Plugin - Enabled as Client\n");
         }
diff --git a/version.properties b/version.properties
index 565c90526f76bd5b44393925629a22dfb9583363..81be22bfab55c82f1cd48ef9680b5d43e94421c4 100644
--- a/version.properties
+++ b/version.properties
@@ -1,4 +1,4 @@
 [VERSION]  
 major = 1  
 minor = 2
-build = 11
+build = 13