diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 1d1616ed673..8f8521758d8 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -173,21 +173,33 @@ template bool LR11x0Interface::reconfigure() // set mode to standby setStandby(); - // configure publicly accessible settings + // The caller reboots the device when reconfigure returns false; track + // every SPI setter so we don't silently report success after a glitch. + bool ok = true; + int err = lora.setSpreadingFactor(sf); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setBandwidth(bw, wideLora() && (getFreq() > 1000.0f)); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setCodingRate(cr, cr != 7); // use long interleaving except if CR is 4/7 which doesn't support it - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setSyncWord(syncWord); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR11x0 setSyncWord %s%d", radioLibErr, err); + ok = false; + } if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) { // clamp if wide freq range limitPower(LR1120_MAX_POWER); @@ -196,14 +208,22 @@ template bool LR11x0Interface::reconfigure() } err = lora.setPreambleLength(preambleLength); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR11x0 setPreambleLength %s%d", radioLibErr, err); + ok = false; + } err = lora.setFrequency(getFreq()); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setOutputPower(power); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR11x0 setOutputPower %s%d", radioLibErr, err); + ok = false; + } // Apply RX gain mode — valid in STDBY, matches resetAGC() pattern err = lora.setRxBoostedGainMode(config.lora.sx126x_rx_boosted_gain); @@ -212,7 +232,7 @@ template bool LR11x0Interface::reconfigure() startReceive(); // restart receiving - return true; + return ok; } template void LR11x0Interface::disableInterrupt() @@ -230,8 +250,6 @@ template void LR11x0Interface::setStandby() LOG_DEBUG("LR11x0 standby failed with error %d", err); } - assert(err == RADIOLIB_ERR_NONE); - isReceiving = false; // If we were receiving, not any more activeReceiveStart = 0; disableInterrupt(); diff --git a/src/mesh/LR20x0Interface.cpp b/src/mesh/LR20x0Interface.cpp index 699663cf032..ed2fe5628c8 100644 --- a/src/mesh/LR20x0Interface.cpp +++ b/src/mesh/LR20x0Interface.cpp @@ -201,21 +201,33 @@ template bool LR20x0Interface::reconfigure() // set mode to standby setStandby(); - // configure publicly accessible settings + // The caller reboots the device when reconfigure returns false; track + // every SPI setter so we don't silently report success after a glitch. + bool ok = true; + int err = lora.setSpreadingFactor(sf); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setBandwidth(bw); // different form than LR11xx - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setCodingRate(cr, cr != 7); // use long interleaving except if CR is 4/7 which doesn't support it - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setSyncWord(syncWord); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR20x0 setSyncWord %s%d", radioLibErr, err); + ok = false; + } if (config.lora.region == meshtastic_Config_LoRaConfig_RegionCode_LORA_24) { // clamp if wide freq range limitPower(LR2021_MAX_POWER_HF); @@ -224,14 +236,22 @@ template bool LR20x0Interface::reconfigure() } err = lora.setPreambleLength(preambleLength); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR20x0 setPreambleLength %s%d", radioLibErr, err); + ok = false; + } err = lora.setFrequency(getFreq()); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setOutputPower(power); - assert(err == RADIOLIB_ERR_NONE); + if (err != RADIOLIB_ERR_NONE) { + LOG_ERROR("LR20x0 setOutputPower %s%d", radioLibErr, err); + ok = false; + } // Apply RX gain mode — valid in STDBY, matches resetAGC() pattern err = lora.setRxBoostedGainMode(config.lora.sx126x_rx_boosted_gain); @@ -240,7 +260,7 @@ template bool LR20x0Interface::reconfigure() startReceive(); // restart receiving - return true; + return ok; } template void LR20x0Interface::disableInterrupt() @@ -258,8 +278,6 @@ template void LR20x0Interface::setStandby() LOG_DEBUG("LR20x0 standby failed with error %d", err); } - assert(err == RADIOLIB_ERR_NONE); - isReceiving = false; // If we were receiving, not any more activeReceiveStart = 0; disableInterrupt(); diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 952a6d2be37..f02257231c9 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -94,8 +94,9 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp) mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) { LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo"); // ignore our request for its NodeInfo - } else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user && - nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) { + } else if (auto *senderNode = (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) ? nodeDB->getMeshNode(mp->from) + : nullptr; + senderNode && !senderNode->has_user && nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) { if (airTime->isTxAllowedChannelUtil(true)) { const int8_t hopsUsed = getHopsAway(*mp, config.lora.hop_limit); if (hopsUsed > (int32_t)(config.lora.hop_limit + 2)) { diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index e8613d45729..48a5175813b 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -349,9 +349,16 @@ int32_t NextHopRouter::doRetransmissions() void NextHopRouter::setNextTx(PendingPacket *pending) { assert(iface); - auto d = iface->getRetransmissionMsec(pending->packet); + // Two nodes that NAK each other will otherwise re-collide on near-identical + // schedules; spread successive attempts with exponential backoff plus jitter. + uint32_t base = iface->getRetransmissionMsec(pending->packet); + uint8_t attempt = (NUM_RELIABLE_RETX - 1) - pending->numRetransmissions; + uint8_t shift = attempt < 3 ? attempt : 3; // cap multiplier at 8x + uint32_t backoff = base << shift; + uint32_t jitter = base ? random(base / 2 + 1) : 0; + uint32_t d = backoff + jitter; pending->nextTxMsec = millis() + d; - LOG_DEBUG("Setting next retransmission in %u msecs: ", d); + LOG_DEBUG("Setting next retransmission in %u msecs (attempt %u): ", d, attempt); printPacket("", pending->packet); setReceivedMessage(); // Run ASAP, so we can figure out our correct sleep time } diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index ac6880adea4..ef07f68fd64 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1881,7 +1881,7 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed(); cn->level = meshtastic_LogRecord_Level_WARNING; cn->time = getValidTime(RTCQualityFromNet); - sprintf(cn->message, warning, p.long_name); + snprintf(cn->message, sizeof(cn->message), warning, p.long_name); service->sendClientNotification(cn); } return false; diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 43149ef8b40..561f0a7baae 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -208,37 +208,51 @@ bool RF95Interface::reconfigure() // set mode to standby setStandby(); - // configure publicly accessible settings + // The caller reboots the device when reconfigure returns false; track + // every SPI setter so we don't silently report success after a glitch. + bool ok = true; + int err = lora->setSpreadingFactor(sf); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora->setBandwidth(bw); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora->setCodingRate(cr); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora->setSyncWord(syncWord); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("RF95 setSyncWord %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora->setCurrentLimit(currentLimit); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("RF95 setCurrentLimit %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora->setPreambleLength(preambleLength); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("RF95 setPreambleLength %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora->setFrequency(getFreq()); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } limitPower(RF95_MAX_POWER); @@ -247,12 +261,14 @@ bool RF95Interface::reconfigure() #else err = lora->setOutputPower(power); #endif - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } startReceive(); // restart receiving - return true; + return ok; } /** diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index de468cf9793..99183d6601c 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -530,7 +530,13 @@ void RadioLibInterface::handleReceiveInterrupt() mp->which_payload_variant = meshtastic_MeshPacket_encrypted_tag; // Mark that the payload is still encrypted at this point - assert(((uint32_t)payloadLen) <= sizeof(mp->encrypted.bytes)); + if ((uint32_t)payloadLen > sizeof(mp->encrypted.bytes)) { + LOG_WARN("Drop oversized RX packet (%d > %u)", payloadLen, (unsigned)sizeof(mp->encrypted.bytes)); + packetPool.release(mp); + rxBad++; + airTime->logAirtime(RX_ALL_LOG, rxMsec); + return; + } memcpy(mp->encrypted.bytes, radioBuffer.payload, payloadLen); mp->encrypted.size = payloadLen; @@ -555,6 +561,17 @@ void RadioLibInterface::pollMissedIrqs() if (isReceiving) { checkRxDoneIrqFlag(); } + if (sendingPacket != NULL) { + checkTxDoneIrqFlag(); + // The stuck-TX guard in canSendImmediately only runs when the queue + // gets new packets. If the queue is empty, a wedged radio sits + // forever — fire the same reboot path here so it always trips. + if (!Throttle::isWithinTimespanMs(lastTxStart, 60000) && rebootAtMsec == 0) { + LOG_ERROR("Hardware Failure! TX stuck for more than 60s (poll)"); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_TRANSMIT_FAILED); + rebootAtMsec = lastTxStart + 65000; + } + } } void RadioLibInterface::resetAGC() @@ -570,6 +587,14 @@ void RadioLibInterface::checkRxDoneIrqFlag() } } +void RadioLibInterface::checkTxDoneIrqFlag() +{ + if (iface->checkIrq(RADIOLIB_IRQ_TX_DONE)) { + LOG_WARN("caught missed TX_DONE"); + notify(ISR_TX, true); + } +} + void RadioLibInterface::configHardwareForSend() { powerMon->setState(meshtastic_PowerMon_State_Lora_TXOn); diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 0740561f9b2..f024457c211 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -293,4 +293,5 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified bool removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt) override; void checkRxDoneIrqFlag(); + void checkTxDoneIrqFlag(); }; diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index ffeb7c5393d..528cd011445 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -168,13 +168,22 @@ int32_t Router::runOnce() */ void Router::enqueueReceivedMessage(meshtastic_MeshPacket *p) { - // Try enqueue until successful - while (!fromRadioQueue.enqueue(p, 0)) { - meshtastic_MeshPacket *old_p; - old_p = fromRadioQueue.dequeuePtr(0); // Dequeue and discard the oldest packet - if (old_p) { - printPacket("fromRadioQ full, drop oldest!", old_p); - packetPool.release(old_p); + // Try enqueue, but if the queue is full and the incoming packet is itself + // low priority, drop *it* rather than evicting an older (likely higher- + // priority) packet such as an ACK or routing reply. + if (!fromRadioQueue.enqueue(p, 0)) { + if (p->priority != meshtastic_MeshPacket_Priority_UNSET && p->priority <= meshtastic_MeshPacket_Priority_BACKGROUND) { + printPacket("fromRadioQ full, drop incoming low-prio!", p); + packetPool.release(p); + return; + } + // Higher-priority packet — fall back to evicting until it fits. + while (!fromRadioQueue.enqueue(p, 0)) { + meshtastic_MeshPacket *old_p = fromRadioQueue.dequeuePtr(0); + if (old_p) { + printPacket("fromRadioQ full, drop oldest!", old_p); + packetPool.release(old_p); + } } } // Nasty hack because our threading is primitive. interfaces shouldn't need to know about routers FIXME @@ -329,7 +338,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) cn->reply_id = p->id; cn->level = meshtastic_LogRecord_Level_WARNING; cn->time = getValidTime(RTCQualityFromNet); - sprintf(cn->message, "Duty cycle limit exceeded. You can send again in %d mins", silentMinutes); + snprintf(cn->message, sizeof(cn->message), "Duty cycle limit exceeded. You can send again in %d mins", silentMinutes); service->sendClientNotification(cn); meshtastic_Routing_Error err = meshtastic_Routing_Error_DUTY_CYCLE_LIMIT; @@ -372,24 +381,32 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it - DEBUG_HEAP_BEFORE; - meshtastic_MeshPacket *p_decoded = packetPool.allocCopy(*p); - DEBUG_HEAP_AFTER("Router::send", p_decoded); + // The pre-encryption copy is only needed to feed MQTT::onSend; skip it + // entirely on builds/devices where MQTT is excluded or disabled. + meshtastic_MeshPacket *p_decoded = nullptr; +#if !MESHTASTIC_EXCLUDE_MQTT + const bool needDecodedForMqtt = moduleConfig.mqtt.enabled && isFromUs(p) && mqtt; + if (needDecodedForMqtt) { + DEBUG_HEAP_BEFORE; + p_decoded = packetPool.allocCopy(*p); + DEBUG_HEAP_AFTER("Router::send", p_decoded); + } +#endif auto encodeResult = perhapsEncode(p); if (encodeResult != meshtastic_Routing_Error_NONE) { - packetPool.release(p_decoded); + if (p_decoded) + packetPool.release(p_decoded); p->channel = 0; // Reset the channel to 0, so we don't use the failing hash again abortSendAndNak(encodeResult, p); return encodeResult; // FIXME - this isn't a valid ErrorCode } #if !MESHTASTIC_EXCLUDE_MQTT - // Only publish to MQTT if we're the original transmitter of the packet - if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) { + if (p_decoded) { mqtt->onSend(*p, *p_decoded, chIndex); + packetPool.release(p_decoded); } #endif - packetPool.release(p_decoded); } #if HAS_UDP_MULTICAST diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 3513bbba3f3..703a11421fc 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -213,37 +213,51 @@ template bool SX126xInterface::reconfigure() // set mode to standby setStandby(); - // configure publicly accessible settings + // The caller reboots the device when reconfigure returns false; track + // every SPI setter so we don't silently report success after a glitch. + bool ok = true; + int err = lora.setSpreadingFactor(sf); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setBandwidth(bw); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setCodingRate(cr); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setSyncWord(syncWord); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX126X setSyncWord %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora.setCurrentLimit(currentLimit); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX126X setCurrentLimit %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora.setPreambleLength(preambleLength); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX126X setPreambleLength %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora.setFrequency(getFreq()); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } limitPower(SX126X_MAX_POWER); // Make sure we reach the minimum power supported to turn the chip on (-9dBm) @@ -251,9 +265,10 @@ template bool SX126xInterface::reconfigure() power = -9; err = lora.setOutputPower(power); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX126X setOutputPower %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } // Apply RX gain mode — valid in STDBY (datasheet §9.6), matches resetAGC() pattern err = lora.setRxBoostedGainMode(config.lora.sx126x_rx_boosted_gain); @@ -262,7 +277,7 @@ template bool SX126xInterface::reconfigure() startReceive(); // restart receiving - return true; + return ok; } template void SX126xInterface::disableInterrupt() @@ -281,8 +296,6 @@ template void SX126xInterface::setStandby() #ifdef ARCH_PORTDUINO if (err != RADIOLIB_ERR_NONE) portduino_status.LoRa_in_error = true; -#else - assert(err == RADIOLIB_ERR_NONE); #endif isReceiving = false; // If we were receiving, not any more activeReceiveStart = 0; diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 64d71921a58..60dc3457247 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -117,43 +117,57 @@ template bool SX128xInterface::reconfigure() // set mode to standby setStandby(); - // configure publicly accessible settings + // The caller reboots the device when reconfigure returns false; track + // every SPI setter so we don't silently report success after a glitch. + bool ok = true; + int err = lora.setSpreadingFactor(sf); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setBandwidth(bw); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setCodingRate(cr, cr != 7); // use long interleaving except if CR is 4/7 which doesn't support it - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } err = lora.setSyncWord(syncWord); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX128X setSyncWord %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora.setPreambleLength(preambleLength); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX128X setPreambleLength %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } err = lora.setFrequency(getFreq()); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_INVALID_RADIO_SETTING); + ok = false; + } limitPower(SX128X_MAX_POWER); err = lora.setOutputPower(power); - if (err != RADIOLIB_ERR_NONE) + if (err != RADIOLIB_ERR_NONE) { LOG_ERROR("SX128X setOutputPower %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); + ok = false; + } startReceive(); // restart receiving - return true; + return ok; } template void SX128xInterface::disableInterrupt() @@ -174,7 +188,6 @@ template void SX128xInterface::setStandby() if (err != RADIOLIB_ERR_NONE) LOG_ERROR("SX128x standby %s%d", radioLibErr, err); - assert(err == RADIOLIB_ERR_NONE); #if ARCH_PORTDUINO if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) { digitalWrite(portduino_config.lora_rxen_pin.pin, LOW);