diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index 17e2fbf5a..5c1cf4c21 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -68,7 +68,6 @@ jobs: - board: tlora-v2-1-1_8 - board: tbeam - board: heltec-ht62-esp32c3-sx1262 - - board: heltec-v1 - board: heltec-v2_0 - board: heltec-v2_1 - board: tbeam0_7 diff --git a/bin/check-all.sh b/bin/check-all.sh index cdd1ceb9d..d1b50a8aa 100755 --- a/bin/check-all.sh +++ b/bin/check-all.sh @@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then # can override which environment by passing arg BOARDS="$@" else - BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo canaryone pca10059_diy_eink" + BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo canaryone pca10059_diy_eink" fi echo "BOARDS:${BOARDS}" diff --git a/bin/check-dependencies.sh b/bin/check-dependencies.sh index 52bc76089..4aa0fccc0 100644 --- a/bin/check-dependencies.sh +++ b/bin/check-dependencies.sh @@ -8,7 +8,7 @@ if [[ $# -gt 0 ]]; then # can override which environment by passing arg BOARDS="$@" else - BOARDS="rak4631 rak4631_eink t-echo canaryone pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core" + BOARDS="rak4631 rak4631_eink t-echo canaryone pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core" fi echo "BOARDS:${BOARDS}" diff --git a/protobufs b/protobufs index 5f28be497..24edea644 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 5f28be497a5518334c86378335e8ffcd177ed661 +Subproject commit 24edea64429de4474c00d09990ef4c496614dc5d diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index addde4edd..08ef116b2 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -444,6 +444,11 @@ bool GPS::setup() if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) { LOG_WARN("Unable to enable powersaving for GPS.\n"); } + msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving details for GPS.\n"); + } // For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats. if (strncmp(info.hwVersion, "00080000", 8) == 0) { msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA); @@ -477,6 +482,12 @@ bool GPS::setup() if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) { LOG_WARN("Unable to enable powersaving mode for GPS.\n"); } + + msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2); + _serial_gps->write(UBXscratch, msglen); + if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) { + LOG_WARN("Unable to enable powersaving details for GPS.\n"); + } } } diff --git a/src/graphics/EInkDisplay2.cpp b/src/graphics/EInkDisplay2.cpp index 10653e25a..de53daaee 100644 --- a/src/graphics/EInkDisplay2.cpp +++ b/src/graphics/EInkDisplay2.cpp @@ -18,7 +18,7 @@ SPIClass *hspi = NULL; #define TECHO_DISPLAY_MODEL GxEPD2_154_D67 #elif defined(RAK4630) -// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update +// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give fast refresh // support #define TECHO_DISPLAY_MODEL GxEPD2_213_BN @@ -65,7 +65,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY // GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 setGeometry(GEOMETRY_RAWMODE, 250, 122); - + this->displayBufferSize = 250 * (128 / 8); // GxEPD2_420_M01 // setGeometry(GEOMETRY_RAWMODE, 300, 400); @@ -131,8 +131,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit) // No need to grab this lock because we are on our own SPI bus // concurrency::LockGuard g(spiLock); -#if defined(USE_EINK_DYNAMIC_PARTIAL) - // Decide if update is partial or full +#if defined(USE_EINK_DYNAMIC_REFRESH) + // Decide between full refresh, fast refresh, or skipping the update bool continueUpdate = determineRefreshMode(); if (!continueUpdate) return false; @@ -165,12 +165,12 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit) adafruitDisplay->nextPage(); #elif defined(RAK4630) || defined(MAKERPYTHON) - // RAK14000 2.13 inch b/w 250x122 actually now does support partial updates + // RAK14000 2.13 inch b/w 250x122 actually now does support fast refresh // Full update mode (slow) - // adafruitDisplay->display(false); // FIXME, use partial update mode + // adafruitDisplay->display(false); // FIXME, use fast refresh mode - // Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false); + // Only enable for e-Paper with support for fast updates and comment out above adafruitDisplay->display(false); // 1.54 inch 200x200 - GxEPD2_154_M09 // 2.13 inch 250x122 - GxEPD2_213_BN // 2.9 inch 296x128 - GxEPD2_290_T5D @@ -203,7 +203,7 @@ void EInkDisplay::display(void) // at least one forceDisplay() keyframe. This prevents flashing when we should the critical // bootscreen (that we want to look nice) -#ifdef USE_EINK_DYNAMIC_PARTIAL +#ifdef USE_EINK_DYNAMIC_REFRESH lowPriority(); forceDisplay(); highPriority(); @@ -257,9 +257,9 @@ bool EInkDisplay::connect() auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY); adafruitDisplay = new GxEPD2_BW(*lowLevel); adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0)); - // RAK14000 2.13 inch b/w 250x122 does actually now support partial updates + // RAK14000 2.13 inch b/w 250x122 does actually now support fast refresh adafruitDisplay->setRotation(3); - // Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2 + // Fast refresh support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2 // adafruitDisplay->setRotation(1); adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight); } else { @@ -347,10 +347,10 @@ bool EInkDisplay::connect() return true; } -// Use a mix of full and partial refreshes, to preserve display health -#if defined(USE_EINK_DYNAMIC_PARTIAL) +// Use a mix of full refresh, fast refresh, and update skipping, to balance urgency and display health +#if defined(USE_EINK_DYNAMIC_REFRESH) -// Suggest that subsequent updates should use partial-refresh +// Suggest that subsequent updates should use fast-refresh void EInkDisplay::highPriority() { isHighPriority = true; @@ -362,8 +362,14 @@ void EInkDisplay::lowPriority() isHighPriority = false; } -// configure display for partial-refresh -void EInkDisplay::configForPartialRefresh() +// Full-refresh is explicitly requested for next one update - no skipping please +void EInkDisplay::demandFullRefresh() +{ + demandingFull = true; +} + +// configure display for fast-refresh +void EInkDisplay::configForFastRefresh() { // Display-specific code can go here #if defined(PRIVATE_HW) @@ -384,6 +390,49 @@ void EInkDisplay::configForFullRefresh() #endif } +#ifdef EINK_FASTREFRESH_ERASURE_LIMIT +// Count black pixels in an image. Used for "erasure tracking" +int32_t EInkDisplay::countBlackPixels() +{ + int32_t blackCount = 0; // Signed, to avoid underflow when comparing + for (uint16_t b = 0; b < (displayWidth / 8) * displayHeight; b++) { + for (uint8_t i = 0; i < 7; i++) { + // Check if each bit is black or white + blackCount += (buffer[b] >> i) & 1; + } + } + return blackCount; +} + +// Evaluate the (rough) amount of black->white pixel change since last full refresh +bool EInkDisplay::tooManyErasures() +{ + // Ideally, we would compare the new and old buffers, to count *actual* white-to-black pixel changes + // but that would require substantially more "code tampering" + + // Get the black pixel stats for this image + int32_t blackCount = countBlackPixels(); + int32_t blackDifference = blackCount - prevBlackCount; + + // Update the running total of "erasures" - black pixels which have become white, since last full-refresh + if (blackDifference < 0) + erasedSinceFull -= blackDifference; + + // Store black pixel count for next time + prevBlackCount = blackCount; + + // Log the running total - help devs setup new boards + LOG_DEBUG("Dynamic Refresh: erasedSinceFull=%hu, EINK_FASTREFRESH_ERASURE_LIMIT=%hu\n", erasedSinceFull, + EINK_FASTREFRESH_ERASURE_LIMIT); + + // Check if too many pixels have been erased + if (erasedSinceFull > EINK_FASTREFRESH_ERASURE_LIMIT) + return true; // Too many + else + return false; // Still okay +} +#endif // ifdef EINK_FASTREFRESH_ERASURE_LIMIT + bool EInkDisplay::newImageMatchesOld() { uint32_t newImageHash = 0; @@ -403,7 +452,7 @@ bool EInkDisplay::newImageMatchesOld() return hashMatches; } -// Change between partial and full refresh config, or skip update, balancing urgency and display health. +// Choose between, full-refresh, fast refresh, and update skipping, to balance urgency and display health. bool EInkDisplay::determineRefreshMode() { uint32_t now = millis(); @@ -416,25 +465,36 @@ bool EInkDisplay::determineRefreshMode() missedHighPriorityUpdate = false; } - // Abort: if too soon for a new frame - if (isHighPriority && partialRefreshCount > 0 && sinceLast < highPriorityLimitMsec) { - LOG_DEBUG("Update skipped: exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n"); + // Abort: if too soon for a new frame (unless demanding full) + if (!demandingFull && isHighPriority && fastRefreshCount > 0 && sinceLast < highPriorityLimitMsec) { + LOG_DEBUG("Dynamic Refresh: update skipped. Exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n"); missedHighPriorityUpdate = true; return false; } - if (!isHighPriority && sinceLast < lowPriorityLimitMsec) { + if (!demandingFull && !isHighPriority && !demandingFull && sinceLast < lowPriorityLimitMsec) { return false; } - // Check if old image (partial) should be redrawn (as full), for image quality - if (partialRefreshCount > 0 && !isHighPriority) + // If demanded full refresh: give it to them + if (demandingFull) needsFull = true; - // If too many partials, require a full-refresh (display health) - if (partialRefreshCount >= partialRefreshLimit) + // Check if old image (fast-refresh) should be redrawn (as full), for image quality + if (fastRefreshCount > 0 && !isHighPriority) needsFull = true; + // If too many fast updates, require a full-refresh (display health) + if (fastRefreshCount >= fastRefreshLimit) + needsFull = true; + +#ifdef EINK_FASTREFRESH_ERASURE_LIMIT + // Some displays struggle with erasing black pixels to white, during fast-refresh + if (tooManyErasures()) + needsFull = true; +#endif + // If image matches + // (Block must run, even if full already selected, to store hash for next time) if (newImageMatchesOld()) { // If low priority: limit rate // otherwise, every loop() will run the hash method @@ -450,27 +510,29 @@ bool EInkDisplay::determineRefreshMode() // If options require a full refresh if (!isHighPriority || needsFull) { - if (partialRefreshCount > 0) + if (fastRefreshCount > 0) configForFullRefresh(); - LOG_DEBUG("Conditions met for full-refresh\n"); - partialRefreshCount = 0; + LOG_DEBUG("Dynamic Refresh: conditions met for full-refresh\n"); + fastRefreshCount = 0; needsFull = false; + demandingFull = false; + erasedSinceFull = 0; // Reset the count for EINK_FASTREFRESH_ERASURE_LIMIT - tracks ghosting buildup } - // If options allow a partial refresh + // If options allow a fast-refresh else { - if (partialRefreshCount == 0) - configForPartialRefresh(); + if (fastRefreshCount == 0) + configForFastRefresh(); - LOG_DEBUG("Conditions met for partial-refresh\n"); - partialRefreshCount++; + LOG_DEBUG("Dynamic Refresh: conditions met for fast-refresh\n"); + fastRefreshCount++; } lastUpdateMsec = now; // Mark time for rate limiting return true; // Instruct calling method to continue with update } -#endif // End USE_EINK_DYNAMIC_PARTIAL +#endif // End USE_EINK_DYNAMIC_REFRESH #endif diff --git a/src/graphics/EInkDisplay2.h b/src/graphics/EInkDisplay2.h index 91261c865..260a79755 100644 --- a/src/graphics/EInkDisplay2.h +++ b/src/graphics/EInkDisplay2.h @@ -55,67 +55,80 @@ class EInkDisplay : public OLEDDisplay // Connect to the display virtual bool connect() override; -#if defined(USE_EINK_DYNAMIC_PARTIAL) - // Full, partial, or skip: balance urgency with display health +#if defined(USE_EINK_DYNAMIC_REFRESH) + // Full, fast, or skip: balance urgency with display health - // Use partial refresh if EITHER: + // Use fast refresh if EITHER: // * highPriority() was set // * a highPriority() update was previously skipped, for rate-limiting - (EINK_HIGHPRIORITY_LIMIT_SECONDS) // Use full refresh if EITHER: // * lowPriority() was set - // * too many partial updates in a row: protect display - (EINK_PARTIAL_REPEAT_LIMIT) - // * no recent updates, and last update was partial: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS) + // * demandFullRefresh() was called - (single shot) + // * too many fast updates in a row: protect display - (EINK_FASTREFRESH_REPEAT_LIMIT) + // * no recent updates, and last update was fast: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS) + // * (optional) too many "erasures" since full-refresh (black pixels cleared to white) // Rate limit if: // * lowPriority() - (EINK_LOWPRIORITY_LIMIT_SECONDS) - // * highPriority(), if multiple partials have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS) + // * highPriority(), if multiple fast updates have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS) // Skip update entirely if ALL criteria met: // * new image matches old image // * lowPriority() + // * no call to demandFullRefresh() // * not redrawing for image quality // * not refreshing for display health // ------------------------------------ // To implement for your E-Ink display: - // * edit configForPartialRefresh() + // * edit configForFastRefresh() // * edit configForFullRefresh() // * add macros to variant.h, and adjust to taste: /* - #define USE_EINK_DYNAMIC_PARTIAL + #define USE_EINK_DYNAMIC_REFRESH #define EINK_LOWPRIORITY_LIMIT_SECONDS 30 #define EINK_HIGHPRIORITY_LIMIT_SECONDS 1 - #define EINK_PARTIAL_REPEAT_LIMIT 5 + #define EINK_FASTREFRESH_REPEAT_LIMIT 5 + #define EINK_FASTREFRESH_ERASURE_LIMIT 300 // optional */ public: - void highPriority(); // Suggest partial refresh - void lowPriority(); // Suggest full refresh + void highPriority(); // Suggest fast refresh + void lowPriority(); // Suggest full refresh + void demandFullRefresh(); // For next update: explicitly request full refresh protected: - void configForPartialRefresh(); // Display specific code to select partial refresh mode - void configForFullRefresh(); // Display specific code to return to full refresh mode - bool newImageMatchesOld(); // Is the new update actually different to the last image? - bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update + void configForFastRefresh(); // Display specific code to select fast refresh mode + void configForFullRefresh(); // Display specific code to return to full refresh mode + bool newImageMatchesOld(); // Is the new update actually different to the last image? + bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update +#ifdef EINK_FASTREFRESH_ERASURE_LIMIT + int32_t countBlackPixels(); // Calculate the number of black pixels in the new image + bool tooManyErasures(); // Has too much "ghosting" (black pixels erased to white) accumulated since last full-refresh? +#endif bool isHighPriority = true; // Does the method calling update believe that this is urgent? bool needsFull = false; // Is a full refresh forced? (display health) + bool demandingFull = false; // Was full refresh specifically requested? (splash screens, etc) bool missedHighPriorityUpdate = false; // Was a high priority update skipped for rate-limiting? - uint16_t partialRefreshCount = 0; // How many partials have occurred since last full refresh? + uint16_t fastRefreshCount = 0; // How many fast updates have occurred since last full refresh? uint32_t lastUpdateMsec = 0; // When did the last update occur? uint32_t prevImageHash = 0; // Used to check if update will change screen image (skippable or not) + int32_t prevBlackCount = 0; // How many black pixels were in the previous image + uint32_t erasedSinceFull = 0; // How many black pixels have been set back to white since last full-refresh? (roughly) // Set in variant.h - const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for partial refreshes + const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for fast refreshes const uint32_t highPriorityLimitMsec = (uint32_t)1000 * EINK_HIGHPRIORITY_LIMIT_SECONDS; // Max rate for full refreshes - const uint32_t partialRefreshLimit = EINK_PARTIAL_REPEAT_LIMIT; // Max consecutive partials, before full is triggered + const uint32_t fastRefreshLimit = EINK_FASTREFRESH_REPEAT_LIMIT; // Max consecutive fast updates, before full is triggered -#else // !USE_EINK_DYNAMIC_PARTIAL +#else // !USE_EINK_DYNAMIC_REFRESH // Tolerate calls to these methods anywhere, just to be safe void highPriority() {} void lowPriority() {} + void demandFullRefresh() {} #endif }; diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 80bcc10c6..fe1041d3d 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -87,6 +87,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex) channelSettings.psk.bytes[0] = defaultpskIndex; channelSettings.psk.size = 1; strncpy(channelSettings.name, "", sizeof(channelSettings.name)); + channelSettings.module_settings.position_precision = 32; // default to sending location on the primary channel ch.has_settings = true; ch.role = meshtastic_Channel_Role_PRIMARY; diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index d27d47e87..db3f3f35e 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -21,7 +21,7 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) { if (wasSeenRecently(p)) { // Note: this will also add a recent packet record printPacket("Ignoring incoming msg, because we've already seen it", p); - if (!moduleConfig.mqtt.enabled && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && + if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT && config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { // cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater! diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 492ed962b..4a6dc9007 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -257,10 +257,9 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) return encodeResult; // FIXME - this isn't a valid ErrorCode } - if (moduleConfig.mqtt.enabled) { - LOG_INFO("Should encrypt MQTT?: %d\n", moduleConfig.mqtt.encryption_enabled); - if (mqtt) - mqtt->onSend(*p, *p_decoded, chIndex); + // Only publish to MQTT if we're the original transmitter of the packet + if (moduleConfig.mqtt.enabled && p->from == nodeDB.getNodeNum() && mqtt) { + mqtt->onSend(*p, *p_decoded, chIndex); } packetPool.release(p_decoded); } @@ -438,6 +437,8 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src) { // Also, we should set the time from the ISR and it should have msec level resolution p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone + // Store a copy of encrypted packet for MQTT + meshtastic_MeshPacket *p_encrypted = packetPool.allocCopy(*p); // Take those raw bytes and convert them back into a well structured protobuf we can understand bool decoded = perhapsDecode(p); @@ -449,10 +450,16 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src) printPacket("handleReceived(USER)", p); else printPacket("handleReceived(REMOTE)", p); + + // Publish received message to MQTT if we're not the original transmitter of the packet + if (moduleConfig.mqtt.enabled && getFrom(p) != nodeDB.getNodeNum() && mqtt) + mqtt->onSend(*p_encrypted, *p, p->channel); } else { printPacket("packet decoding failed or skipped (no PSK?)", p); } + packetPool.release(p_encrypted); // Release the encrypted packet + // call modules here MeshModule::callPlugins(*p, src); } @@ -474,4 +481,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p) handleReceived(p); packetPool.release(p); -} +} \ No newline at end of file diff --git a/src/mesh/generated/meshtastic/apponly.pb.h b/src/mesh/generated/meshtastic/apponly.pb.h index c9c120efa..253fdd8ef 100644 --- a/src/mesh/generated/meshtastic/apponly.pb.h +++ b/src/mesh/generated/meshtastic/apponly.pb.h @@ -54,7 +54,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg; #define meshtastic_ChannelSet_fields &meshtastic_ChannelSet_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_ChannelSet_size 594 +#define meshtastic_ChannelSet_size 658 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/atak.pb.h b/src/mesh/generated/meshtastic/atak.pb.h index 71c3c387f..17d3cd3b9 100644 --- a/src/mesh/generated/meshtastic/atak.pb.h +++ b/src/mesh/generated/meshtastic/atak.pb.h @@ -110,7 +110,7 @@ typedef struct _meshtastic_PLI { in floating point */ int32_t longitude_i; /* Altitude (ATAK prefers HAE) */ - uint32_t altitude; + int32_t altitude; /* Speed */ uint32_t speed; /* Course in degrees */ @@ -238,7 +238,7 @@ X(a, STATIC, SINGULAR, STRING, device_callsign, 2) #define meshtastic_PLI_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \ X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \ -X(a, STATIC, SINGULAR, UINT32, altitude, 3) \ +X(a, STATIC, SINGULAR, INT32, altitude, 3) \ X(a, STATIC, SINGULAR, UINT32, speed, 4) \ X(a, STATIC, SINGULAR, UINT32, course, 5) #define meshtastic_PLI_CALLBACK NULL @@ -263,7 +263,7 @@ extern const pb_msgdesc_t meshtastic_PLI_msg; #define meshtastic_Contact_size 242 #define meshtastic_GeoChat_size 323 #define meshtastic_Group_size 4 -#define meshtastic_PLI_size 26 +#define meshtastic_PLI_size 31 #define meshtastic_Status_size 3 #define meshtastic_TAKPacket_size 584 diff --git a/src/mesh/generated/meshtastic/channel.pb.c b/src/mesh/generated/meshtastic/channel.pb.c index 62585fd17..f604f64e9 100644 --- a/src/mesh/generated/meshtastic/channel.pb.c +++ b/src/mesh/generated/meshtastic/channel.pb.c @@ -9,6 +9,9 @@ PB_BIND(meshtastic_ChannelSettings, meshtastic_ChannelSettings, AUTO) +PB_BIND(meshtastic_ModuleSettings, meshtastic_ModuleSettings, AUTO) + + PB_BIND(meshtastic_Channel, meshtastic_Channel, AUTO) diff --git a/src/mesh/generated/meshtastic/channel.pb.h b/src/mesh/generated/meshtastic/channel.pb.h index 535962ae6..1587483c0 100644 --- a/src/mesh/generated/meshtastic/channel.pb.h +++ b/src/mesh/generated/meshtastic/channel.pb.h @@ -30,6 +30,12 @@ typedef enum _meshtastic_Channel_Role { } meshtastic_Channel_Role; /* Struct definitions */ +/* This message is specifically for modules to store per-channel configuration data. */ +typedef struct _meshtastic_ModuleSettings { + /* Bits of precision for the location sent in position packets. */ + uint32_t position_precision; +} meshtastic_ModuleSettings; + typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t; /* This information can be encoded as a QRcode/url so that other users can configure their radio to join the same channel. @@ -85,6 +91,9 @@ typedef struct _meshtastic_ChannelSettings { bool uplink_enabled; /* If true, messages seen on the internet will be forwarded to the local mesh. */ bool downlink_enabled; + /* Per-channel module settings. */ + bool has_module_settings; + meshtastic_ModuleSettings module_settings; } meshtastic_ChannelSettings; /* A pair of a channel number, mode and the (sharable) settings for that channel */ @@ -111,22 +120,27 @@ extern "C" { #define _meshtastic_Channel_Role_ARRAYSIZE ((meshtastic_Channel_Role)(meshtastic_Channel_Role_SECONDARY+1)) + #define meshtastic_Channel_role_ENUMTYPE meshtastic_Channel_Role /* Initializer values for message structs */ -#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0} +#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default} +#define meshtastic_ModuleSettings_init_default {0} #define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN} -#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0} +#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero} +#define meshtastic_ModuleSettings_init_zero {0} #define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN} /* Field tags (for use in manual encoding/decoding) */ +#define meshtastic_ModuleSettings_position_precision_tag 1 #define meshtastic_ChannelSettings_channel_num_tag 1 #define meshtastic_ChannelSettings_psk_tag 2 #define meshtastic_ChannelSettings_name_tag 3 #define meshtastic_ChannelSettings_id_tag 4 #define meshtastic_ChannelSettings_uplink_enabled_tag 5 #define meshtastic_ChannelSettings_downlink_enabled_tag 6 +#define meshtastic_ChannelSettings_module_settings_tag 7 #define meshtastic_Channel_index_tag 1 #define meshtastic_Channel_settings_tag 2 #define meshtastic_Channel_role_tag 3 @@ -138,9 +152,16 @@ X(a, STATIC, SINGULAR, BYTES, psk, 2) \ X(a, STATIC, SINGULAR, STRING, name, 3) \ X(a, STATIC, SINGULAR, FIXED32, id, 4) \ X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \ -X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) +X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \ +X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) #define meshtastic_ChannelSettings_CALLBACK NULL #define meshtastic_ChannelSettings_DEFAULT NULL +#define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings + +#define meshtastic_ModuleSettings_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, position_precision, 1) +#define meshtastic_ModuleSettings_CALLBACK NULL +#define meshtastic_ModuleSettings_DEFAULT NULL #define meshtastic_Channel_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, index, 1) \ @@ -151,15 +172,18 @@ X(a, STATIC, SINGULAR, UENUM, role, 3) #define meshtastic_Channel_settings_MSGTYPE meshtastic_ChannelSettings extern const pb_msgdesc_t meshtastic_ChannelSettings_msg; +extern const pb_msgdesc_t meshtastic_ModuleSettings_msg; extern const pb_msgdesc_t meshtastic_Channel_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define meshtastic_ChannelSettings_fields &meshtastic_ChannelSettings_msg +#define meshtastic_ModuleSettings_fields &meshtastic_ModuleSettings_msg #define meshtastic_Channel_fields &meshtastic_Channel_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_ChannelSettings_size 62 -#define meshtastic_Channel_size 77 +#define meshtastic_ChannelSettings_size 70 +#define meshtastic_Channel_size 85 +#define meshtastic_ModuleSettings_size 6 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index b8e79fe6b..c56cf65a0 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -317,9 +317,6 @@ typedef struct _meshtastic_Config_PositionConfig { uint32_t gps_en_gpio; /* Set where GPS is enabled, disabled, or not present */ meshtastic_Config_PositionConfig_GpsMode gps_mode; - /* Set GPS precision in bits per channel, or 0 for disabled */ - pb_size_t channel_precision_count; - uint32_t channel_precision[8]; } meshtastic_Config_PositionConfig; /* Power Config\ @@ -587,7 +584,7 @@ extern "C" { /* Initializer values for message structs */ #define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}} #define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} -#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}} +#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} @@ -596,7 +593,7 @@ extern "C" { #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}} #define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0} -#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}} +#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN} #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} @@ -628,7 +625,6 @@ extern "C" { #define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11 #define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12 #define meshtastic_Config_PositionConfig_gps_mode_tag 13 -#define meshtastic_Config_PositionConfig_channel_precision_tag 14 #define meshtastic_Config_PowerConfig_is_power_saving_tag 1 #define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2 #define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3 @@ -732,8 +728,7 @@ X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \ X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \ X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \ X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12) \ -X(a, STATIC, SINGULAR, UENUM, gps_mode, 13) \ -X(a, STATIC, REPEATED, UINT32, channel_precision, 14) +X(a, STATIC, SINGULAR, UENUM, gps_mode, 13) #define meshtastic_Config_PositionConfig_CALLBACK NULL #define meshtastic_Config_PositionConfig_DEFAULT NULL @@ -839,7 +834,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; #define meshtastic_Config_LoRaConfig_size 80 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_size 196 -#define meshtastic_Config_PositionConfig_size 110 +#define meshtastic_Config_PositionConfig_size 62 #define meshtastic_Config_PowerConfig_size 40 #define meshtastic_Config_size 199 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index bca305c14..735644c47 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -312,11 +312,11 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg; #define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_ChannelFile_size 638 +#define meshtastic_ChannelFile_size 702 #define meshtastic_DeviceState_size 17062 #define meshtastic_NodeInfoLite_size 153 #define meshtastic_NodeRemoteHardwarePin_size 29 -#define meshtastic_OEMStore_size 3294 +#define meshtastic_OEMStore_size 3246 #define meshtastic_PositionLite_size 28 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 644d965ab..7d39da01f 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; #define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg /* Maximum encoded size of messages (where known) */ -#define meshtastic_LocalConfig_size 517 +#define meshtastic_LocalConfig_size 469 #define meshtastic_LocalModuleConfig_size 631 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 6c3a9729f..e8a27d43f 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -380,6 +380,8 @@ typedef struct _meshtastic_Position { /* A sequence number, incremented with each Position message to help detect lost updates if needed */ uint32_t seq_number; + /* Indicates the bits of precision set by the sending node */ + uint32_t precision_bits; } meshtastic_Position; /* Broadcast when a newly powered mesh node wants to find a node num it can use @@ -882,7 +884,7 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN} #define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}} @@ -900,7 +902,7 @@ extern "C" { #define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}} #define meshtastic_Neighbor_init_default {0, 0, 0, 0} #define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0} -#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN} #define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} #define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}} @@ -942,6 +944,7 @@ extern "C" { #define meshtastic_Position_sensor_id_tag 20 #define meshtastic_Position_next_update_tag 21 #define meshtastic_Position_seq_number_tag 22 +#define meshtastic_Position_precision_bits_tag 23 #define meshtastic_User_id_tag 1 #define meshtastic_User_long_name_tag 2 #define meshtastic_User_short_name_tag 3 @@ -1068,7 +1071,8 @@ X(a, STATIC, SINGULAR, UINT32, fix_type, 18) \ X(a, STATIC, SINGULAR, UINT32, sats_in_view, 19) \ X(a, STATIC, SINGULAR, UINT32, sensor_id, 20) \ X(a, STATIC, SINGULAR, UINT32, next_update, 21) \ -X(a, STATIC, SINGULAR, UINT32, seq_number, 22) +X(a, STATIC, SINGULAR, UINT32, seq_number, 22) \ +X(a, STATIC, SINGULAR, UINT32, precision_bits, 23) #define meshtastic_Position_CALLBACK NULL #define meshtastic_Position_DEFAULT NULL @@ -1313,8 +1317,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; #define meshtastic_MyNodeInfo_size 18 #define meshtastic_NeighborInfo_size 258 #define meshtastic_Neighbor_size 22 -#define meshtastic_NodeInfo_size 263 -#define meshtastic_Position_size 137 +#define meshtastic_NodeInfo_size 270 +#define meshtastic_Position_size 144 #define meshtastic_QueueStatus_size 23 #define meshtastic_RouteDiscovery_size 40 #define meshtastic_Routing_size 42 diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index e82362bc6..d90df89e9 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -23,6 +23,7 @@ PositionModule::PositionModule() : ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg), concurrency::OSThread("PositionModule") { + precision = 0; // safe starting value isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER && config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) @@ -82,21 +83,15 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes } nodeDB.updatePosition(getFrom(&mp), p); - - // Only respond to location requests on the channel where we broadcast location. - if (channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) { - ignoreRequest = false; - } else { - ignoreRequest = true; - } + precision = channels.getByIndex(mp.channel).settings.module_settings.position_precision; return false; // Let others look at this message also if they want } meshtastic_MeshPacket *PositionModule::allocReply() { - if (ignoreRequest) { - ignoreRequest = false; // Reset for next request + if (precision == 0) { + LOG_DEBUG("Skipping location send because precision is set to 0!\n"); return nullptr; } @@ -116,8 +111,16 @@ meshtastic_MeshPacket *PositionModule::allocReply() localPosition.seq_number++; // lat/lon are unconditionally included - IF AVAILABLE! - p.latitude_i = localPosition.latitude_i; - p.longitude_i = localPosition.longitude_i; + LOG_DEBUG("Sending location with precision %i\n", precision); + p.latitude_i = localPosition.latitude_i & (INT32_MAX << (32 - precision)); + p.longitude_i = localPosition.longitude_i & (INT32_MAX << (32 - precision)); + + // We want the imprecise position to be the middle of the possible location, not + if (precision < 31 && precision > 1) { + p.latitude_i += (1 << 31 - precision); + p.longitude_i += (1 << 31 - precision); + } + p.precision_bits = precision; p.time = localPosition.time; if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) { @@ -164,7 +167,7 @@ meshtastic_MeshPacket *PositionModule::allocReply() LOG_INFO("Providing time to mesh %u\n", p.time); } - LOG_INFO("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i); + LOG_INFO("Position reply: time=%i, latI=%i, lonI=%i\n", p.time, p.latitude_i, p.longitude_i); // TAK Tracker devices should send their position in a TAK packet over the ATAK port if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) @@ -193,7 +196,7 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli() {.pli = { .latitude_i = localPosition.latitude_i, .longitude_i = localPosition.longitude_i, - .altitude = localPosition.altitude_hae > 0 ? localPosition.altitude_hae : 0, + .altitude = localPosition.altitude_hae, .speed = localPosition.ground_speed, .course = static_cast(localPosition.ground_track), }}}; @@ -213,9 +216,12 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal) service.cancelSending(prevPacketId); + // Set's the class precision value for this particular packet + precision = channels.getByIndex(channel).settings.module_settings.position_precision; + meshtastic_MeshPacket *p = allocReply(); if (p == nullptr) { - LOG_WARN("allocReply returned a nullptr\n"); + LOG_DEBUG("allocReply returned a nullptr\n"); return; } diff --git a/src/modules/PositionModule.h b/src/modules/PositionModule.h index bd7a9def4..fddafef6f 100644 --- a/src/modules/PositionModule.h +++ b/src/modules/PositionModule.h @@ -50,6 +50,7 @@ class PositionModule : public ProtobufModule, private concu private: struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition); meshtastic_MeshPacket *allocAtakPli(); + uint32_t precision; /** Only used in power saving trackers for now */ void clearPosition(); diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 8d7c329a2..8c241a302 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -485,14 +485,15 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket & env->channel_id = (char *)channelId; env->gateway_id = owner.id; + LOG_DEBUG("MQTT onSend - Publishing "); if (moduleConfig.mqtt.encryption_enabled) { env->packet = (meshtastic_MeshPacket *)∓ + LOG_DEBUG("encrypted message\n"); } else { env->packet = (meshtastic_MeshPacket *)&mp_decoded; + LOG_DEBUG("portnum %i message\n", env->packet->decoded.portnum); } - LOG_DEBUG("MQTT onSend - Publishing portnum %i message\n", env->packet->decoded.portnum); - if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) { // FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets static uint8_t bytes[meshtastic_MeshPacket_size + 64]; diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index dfcb75b7d..2b803e3fc 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -50,7 +50,8 @@ class MQTT : private concurrency::OSThread /** * Publish a packet on the global MQTT server. - * This hook must be called **after** the packet is encrypted (including the channel being changed to a hash). + * @param mp the encrypted packet to publish + * @param mp_decoded the decrypted packet to publish * @param chIndex the index of the channel for this message * * Note: for messages we are forwarding on the mesh that we can't find the channel for (because we don't have the keys), we diff --git a/variants/heltec_wireless_paper_v1/variant.h b/variants/heltec_wireless_paper_v1/variant.h index 166b7f30e..25e061938 100644 --- a/variants/heltec_wireless_paper_v1/variant.h +++ b/variants/heltec_wireless_paper_v1/variant.h @@ -6,12 +6,12 @@ #define USE_EINK -// Settings for Dynamic Partial mode -// Change between partial and full refresh config, or skip update, balancing urgency and display health. -#define USE_EINK_DYNAMIC_PARTIAL +// Settings for Dynamic Refresh mode +// Change between full-refresh, fast-refresh, or update-skipping, to balance urgency and display health. +#define USE_EINK_DYNAMIC_REFRESH #define EINK_LOWPRIORITY_LIMIT_SECONDS 30 #define EINK_HIGHPRIORITY_LIMIT_SECONDS 1 -#define EINK_PARTIAL_REPEAT_LIMIT 5 +#define EINK_FASTREFRESH_REPEAT_LIMIT 5 /* * eink display pins