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