From d4b627a60c6e60a07f7410939cd7ee4a71c3ce69 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 2 Apr 2026 14:19:50 -0500 Subject: [PATCH] Implement batched NodeInfo encoding for more efficient large NodeDB transfer --- src/mesh/PhoneAPI.cpp | 140 +++++++++++++++++++--- src/mesh/PhoneAPI.h | 8 +- src/mesh/StreamAPI.cpp | 4 +- src/mesh/generated/meshtastic/mesh.pb.cpp | 3 + src/mesh/generated/meshtastic/mesh.pb.h | 31 ++++- src/nimble/NimbleBluetooth.cpp | 6 +- src/platform/nrf52/NRF52Bluetooth.cpp | 2 +- 7 files changed, 167 insertions(+), 27 deletions(-) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 7df6720a2..70ef14c9b 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -18,10 +18,7 @@ #include "concurrency/LockGuard.h" #include "main.h" #include "xmodem.h" - -#if FromRadio_size > MAX_TO_FROM_RADIO_SIZE -#error FromRadio is too big -#endif +#include #if ToRadio_size > MAX_TO_FROM_RADIO_SIZE #error ToRadio is too big @@ -61,13 +58,14 @@ void PhoneAPI::handleStartConfig() onConfigStart(); // even if we were already connected - restart our state machine - if (config_nonce == SPECIAL_NONCE_ONLY_NODES) { + if (config_nonce == SPECIAL_NONCE_ONLY_NODES || config_nonce == SPECIAL_NONCE_BATCH_ONLY_NODES) { // If client only wants node info, jump directly to sending nodes state = STATE_SEND_OWN_NODEINFO; LOG_INFO("Client only wants node info, skipping other config"); } else { state = STATE_SEND_MY_INFO; } + batchNodeInfo = (config_nonce == SPECIAL_NONCE_BATCH || config_nonce == SPECIAL_NONCE_BATCH_ONLY_NODES); pauseBluetoothLogging = true; spiLock->lock(); filesManifest = getFiles("/", 10); @@ -223,6 +221,48 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength) STATE_SEND_PACKETS // send packets or debug strings */ +/// Context passed to the nanopb encoding callback for batched NodeInfo +struct NodeInfoBatchEncodeContext { + std::deque *items; + size_t itemCount; // How many items from the front of the deque to encode +}; + +/// Nanopb encoding callback for repeated NodeInfo items in a NodeInfoBatch. +/// Called by pb_encode during both sizing and actual encoding passes. +static bool nodeInfoBatchEncodeCallback(pb_ostream_t *stream, const pb_field_iter_t *field, void *const *arg) +{ + auto *ctx = static_cast(*arg); + for (size_t i = 0; i < ctx->itemCount && i < ctx->items->size(); i++) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!pb_encode_submessage(stream, meshtastic_NodeInfo_fields, &(*ctx->items)[i])) + return false; + } + return true; +} + +/// Calculate how many NodeInfos from the front of the deque fit within maxPayloadBytes. +/// maxPayloadBytes is the budget for the inner NodeInfoBatch content (repeated field entries). +static size_t calculateBatchCount(std::deque &items, size_t maxPayloadBytes) +{ + size_t totalSize = 0; + size_t count = 0; + for (auto &info : items) { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + if (!pb_encode(&sizestream, meshtastic_NodeInfo_fields, &info)) + break; + size_t itemSize = sizestream.bytes_written; + // Per-item overhead: 1 byte tag (field 1, wire type 2) + varint length prefix + size_t overhead = 1 + (itemSize < 128 ? 1 : 2); + if (totalSize + overhead + itemSize > maxPayloadBytes) + break; + totalSize += overhead + itemSize; + count++; + } + // Always include at least 1 item if available (even if it slightly exceeds budget) + return count > 0 ? count : (items.empty() ? 0 : 1); +} + size_t PhoneAPI::getFromRadio(uint8_t *buf) { // Respond to heartbeat by sending queue status @@ -231,7 +271,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) fromRadioScratch.which_payload_variant = meshtastic_FromRadio_queueStatus_tag; fromRadioScratch.queueStatus = router->getQueueStatus(); heartbeatReceived = false; - size_t numbytes = pb_encode_to_bytes(buf, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch); + size_t numbytes = pb_encode_to_bytes(buf, MAX_TO_FROM_RADIO_SIZE, &meshtastic_FromRadio_msg, &fromRadioScratch); LOG_DEBUG("FromRadio=STATE_SEND_QUEUE_STATUS, numbytes=%u", numbytes); return numbytes; } @@ -286,7 +326,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) nodeInfoForPhone.num = 0; } } - if (config_nonce == SPECIAL_NONCE_ONLY_NODES) { + if (config_nonce == SPECIAL_NONCE_ONLY_NODES || config_nonce == SPECIAL_NONCE_BATCH_ONLY_NODES) { // If client only wants node info, jump directly to sending nodes state = STATE_SEND_OTHER_NODEINFOS; onNowHasData(0); @@ -479,6 +519,81 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) LOG_INFO("Start sending nodeinfos millis=%u", millis()); } + if (batchNodeInfo) { + // Batched path: pack multiple NodeInfos into a single FromRadio packet. + // Consolidate any pending nodeInfoForPhone into the queue, then top it up. + { + concurrency::LockGuard guard(&nodeInfoMutex); + if (nodeInfoForPhone.num != 0) { + nodeInfoQueue.push_front(nodeInfoForPhone); + nodeInfoForPhone = {}; + } + } + prefetchNodeInfos(); + + bool queueEmpty; + { + concurrency::LockGuard guard(&nodeInfoMutex); + queueEmpty = nodeInfoQueue.empty(); + } + + if (queueEmpty) { + LOG_DEBUG("Done sending %d of %d nodeinfos (batched) millis=%u", readIndex, nodeDB->getNumMeshNodes(), millis()); + concurrency::LockGuard guard(&nodeInfoMutex); + nodeInfoQueue.clear(); + state = STATE_SEND_FILEMANIFEST; + return getFromRadio(buf); + } + + // Fix up user IDs and log progress + { + concurrency::LockGuard guard(&nodeInfoMutex); + for (auto &info : nodeInfoQueue) { + sprintf(info.user.id, "!%08x", info.num); + } + } + + // Estimate overhead: FromRadio id (~2B) + oneof tag 18 (~2B) + NodeInfoBatch length varint (~2B) = ~6 bytes + constexpr size_t kFromRadioOverhead = 10; // conservative + size_t batchCount; + { + concurrency::LockGuard guard(&nodeInfoMutex); + batchCount = calculateBatchCount(nodeInfoQueue, MAX_TO_FROM_RADIO_SIZE - kFromRadioOverhead); + } + + if (readIndex == 2 || readIndex % 20 == 0) { + concurrency::LockGuard guard(&nodeInfoMutex); + LOG_DEBUG("nodeinfo batch: %d items, %d/%d total", batchCount, readIndex, nodeDB->getNumMeshNodes()); + } + + // Set up the callback-based encoding. The context must stay alive through pb_encode_to_bytes. + NodeInfoBatchEncodeContext ctx; + { + concurrency::LockGuard guard(&nodeInfoMutex); + ctx.items = &nodeInfoQueue; + ctx.itemCount = batchCount; + } + + fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_batch_tag; + fromRadioScratch.node_info_batch.items.funcs.encode = nodeInfoBatchEncodeCallback; + fromRadioScratch.node_info_batch.items.arg = &ctx; + + // Encode directly here since the callback context is on the stack + size_t numbytes = pb_encode_to_bytes(buf, MAX_TO_FROM_RADIO_SIZE, &meshtastic_FromRadio_msg, &fromRadioScratch); + + // Remove consumed items from the queue + { + concurrency::LockGuard guard(&nodeInfoMutex); + for (size_t i = 0; i < batchCount && !nodeInfoQueue.empty(); i++) { + nodeInfoQueue.pop_front(); + } + } + + prefetchNodeInfos(); + return numbytes; + } + + // Non-batched path: send one NodeInfo per FromRadio packet (legacy behavior) meshtastic_NodeInfo infoToSend = {}; { concurrency::LockGuard guard(&nodeInfoMutex); @@ -496,11 +611,6 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) // Just in case we stored a different user.id in the past, but should never happen going forward sprintf(infoToSend.user.id, "!%08x", infoToSend.num); - // Logging this really slows down sending nodes on initial connection because the serial console is so slow, so only - // uncomment if you really need to: - // LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s", nodeInfoForPhone.num, nodeInfoForPhone.last_heard, - // nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name); - // Occasional progress logging. (readIndex==2 will be true for the first non-us node) if (readIndex == 2 || readIndex % 20 == 0) { LOG_DEBUG("nodeinfo: %d/%d", readIndex, nodeDB->getNumMeshNodes()); @@ -523,8 +633,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) case STATE_SEND_FILEMANIFEST: { LOG_DEBUG("FromRadio=STATE_SEND_FILEMANIFEST"); // last element - if (config_state == filesManifest.size() || - config_nonce == SPECIAL_NONCE_ONLY_NODES) { // also handles an empty filesManifest + if (config_state == filesManifest.size() || config_nonce == SPECIAL_NONCE_ONLY_NODES || + config_nonce == SPECIAL_NONCE_BATCH_ONLY_NODES) { // also handles an empty filesManifest config_state = 0; filesManifest.clear(); // Skip to complete packet @@ -579,7 +689,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) // Do we have a message from the mesh? if (fromRadioScratch.which_payload_variant != 0) { // Encapsulate as a FromRadio packet - size_t numbytes = pb_encode_to_bytes(buf, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch); + size_t numbytes = pb_encode_to_bytes(buf, MAX_TO_FROM_RADIO_SIZE, &meshtastic_FromRadio_msg, &fromRadioScratch); // VERY IMPORTANT to not print debug messages while writing to fromRadioScratch - because we use that same buffer // for logging (when we are encapsulating with protobufs) diff --git a/src/mesh/PhoneAPI.h b/src/mesh/PhoneAPI.h index 7f79b5792..227947e1c 100644 --- a/src/mesh/PhoneAPI.h +++ b/src/mesh/PhoneAPI.h @@ -13,15 +13,14 @@ // Make sure that we never let our packets grow too large for one BLE packet #define MAX_TO_FROM_RADIO_SIZE 512 -#if meshtastic_FromRadio_size > MAX_TO_FROM_RADIO_SIZE -#error "meshtastic_FromRadio_size is too large for our BLE packets" -#endif #if meshtastic_ToRadio_size > MAX_TO_FROM_RADIO_SIZE #error "meshtastic_ToRadio_size is too large for our BLE packets" #endif #define SPECIAL_NONCE_ONLY_CONFIG 69420 #define SPECIAL_NONCE_ONLY_NODES 69421 // ( ͡° ͜ʖ ͡°) +#define SPECIAL_NONCE_BATCH 69422 +#define SPECIAL_NONCE_BATCH_ONLY_NODES 69423 /** * Provides our protobuf based API which phone/PC clients can use to talk to our device @@ -88,6 +87,9 @@ class PhoneAPI // Protect nodeInfoForPhone + nodeInfoQueue because NimBLE callbacks run in a separate FreeRTOS task. concurrency::Lock nodeInfoMutex; + // When true, bundle multiple NodeInfos per FromRadio packet (opt-in via batch nonce) + bool batchNodeInfo = false; + meshtastic_ToRadio toRadioScratch = { 0}; // this is a static scratch object, any data must be copied elsewhere before returning diff --git a/src/mesh/StreamAPI.cpp b/src/mesh/StreamAPI.cpp index 2d9230a21..fc5f6166e 100644 --- a/src/mesh/StreamAPI.cpp +++ b/src/mesh/StreamAPI.cpp @@ -190,7 +190,7 @@ void StreamAPI::emitRebooted() fromRadioScratch.rebooted = true; // LOG_DEBUG("Emitting reboot packet for serial shell"); - emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch)); + emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, MAX_TO_FROM_RADIO_SIZE, &meshtastic_FromRadio_msg, &fromRadioScratch)); } void StreamAPI::emitLogRecord(meshtastic_LogRecord_Level level, const char *src, const char *format, va_list arg) @@ -209,7 +209,7 @@ void StreamAPI::emitLogRecord(meshtastic_LogRecord_Level level, const char *src, if (num_printed > 0 && fromRadioScratch.log_record.message[num_printed - 1] == '\n') // Strip any ending newline, because we have records for framing instead. fromRadioScratch.log_record.message[num_printed - 1] = '\0'; - emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch)); + emitTxBuffer(pb_encode_to_bytes(txBuf + HEADER_LEN, MAX_TO_FROM_RADIO_SIZE, &meshtastic_FromRadio_msg, &fromRadioScratch)); } /// Hookable to find out when connection changes diff --git a/src/mesh/generated/meshtastic/mesh.pb.cpp b/src/mesh/generated/meshtastic/mesh.pb.cpp index 7f1a738c6..28ac3724b 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.cpp +++ b/src/mesh/generated/meshtastic/mesh.pb.cpp @@ -42,6 +42,9 @@ PB_BIND(meshtastic_MeshPacket, meshtastic_MeshPacket, 2) PB_BIND(meshtastic_NodeInfo, meshtastic_NodeInfo, 2) +PB_BIND(meshtastic_NodeInfoBatch, meshtastic_NodeInfoBatch, AUTO) + + PB_BIND(meshtastic_MyNodeInfo, meshtastic_MyNodeInfo, AUTO) diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 477c3b31b..fd450a7c7 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -1037,6 +1037,12 @@ typedef struct _meshtastic_NodeInfo { bool is_muted; } meshtastic_NodeInfo; +/* Batched NodeInfo wrapper for efficient bulk transfer during want_config flow. + Allows multiple NodeInfo messages to be packed into a single FromRadio packet. */ +typedef struct _meshtastic_NodeInfoBatch { + pb_callback_t items; +} meshtastic_NodeInfoBatch; + typedef PB_BYTES_ARRAY_T(16) meshtastic_MyNodeInfo_device_id_t; /* Unique local debugging info for this node Note: we don't include position or the user info, because that will come in the @@ -1262,6 +1268,9 @@ typedef struct _meshtastic_FromRadio { meshtastic_ClientNotification clientNotification; /* Persistent data for device-ui */ meshtastic_DeviceUIConfig deviceuiConfig; + /* Batched NodeInfo messages for efficient bulk transfer. + Used when client opts in via special nonce value. */ + meshtastic_NodeInfoBatch node_info_batch; }; } meshtastic_FromRadio; @@ -1421,6 +1430,7 @@ extern "C" { #define meshtastic_MeshPacket_transport_mechanism_ENUMTYPE meshtastic_MeshPacket_TransportMechanism + #define meshtastic_MyNodeInfo_firmware_edition_ENUMTYPE meshtastic_FirmwareEdition #define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level @@ -1462,6 +1472,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0, 0} +#define meshtastic_NodeInfoBatch_init_default {{{NULL}, NULL}} #define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_default {0, 0, 0, 0} @@ -1495,6 +1506,7 @@ extern "C" { #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0, 0} +#define meshtastic_NodeInfoBatch_init_zero {{{NULL}, NULL}} #define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_QueueStatus_init_zero {0, 0, 0, 0} @@ -1626,6 +1638,7 @@ extern "C" { #define meshtastic_NodeInfo_is_ignored_tag 11 #define meshtastic_NodeInfo_is_key_manually_verified_tag 12 #define meshtastic_NodeInfo_is_muted_tag 13 +#define meshtastic_NodeInfoBatch_items_tag 1 #define meshtastic_MyNodeInfo_my_node_num_tag 1 #define meshtastic_MyNodeInfo_reboot_count_tag 8 #define meshtastic_MyNodeInfo_min_app_version_tag 11 @@ -1700,6 +1713,7 @@ extern "C" { #define meshtastic_FromRadio_fileInfo_tag 15 #define meshtastic_FromRadio_clientNotification_tag 16 #define meshtastic_FromRadio_deviceuiConfig_tag 17 +#define meshtastic_FromRadio_node_info_batch_tag 18 #define meshtastic_Heartbeat_nonce_tag 1 #define meshtastic_ToRadio_packet_tag 1 #define meshtastic_ToRadio_want_config_id_tag 3 @@ -1882,6 +1896,12 @@ X(a, STATIC, SINGULAR, BOOL, is_muted, 13) #define meshtastic_NodeInfo_position_MSGTYPE meshtastic_Position #define meshtastic_NodeInfo_device_metrics_MSGTYPE meshtastic_DeviceMetrics +#define meshtastic_NodeInfoBatch_FIELDLIST(X, a) \ +X(a, CALLBACK, REPEATED, MESSAGE, items, 1) +#define meshtastic_NodeInfoBatch_CALLBACK pb_default_field_callback +#define meshtastic_NodeInfoBatch_DEFAULT NULL +#define meshtastic_NodeInfoBatch_items_MSGTYPE meshtastic_NodeInfo + #define meshtastic_MyNodeInfo_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \ X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \ @@ -1926,7 +1946,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,fileInfo,fileInfo), 15) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,clientNotification,clientNotification), 16) \ -X(a, STATIC, ONEOF, MESSAGE, (payload_variant,deviceuiConfig,deviceuiConfig), 17) +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,deviceuiConfig,deviceuiConfig), 17) \ +X(a, STATIC, ONEOF, MESSAGE, (payload_variant,node_info_batch,node_info_batch), 18) #define meshtastic_FromRadio_CALLBACK NULL #define meshtastic_FromRadio_DEFAULT NULL #define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket @@ -1943,6 +1964,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,deviceuiConfig,deviceuiConfi #define meshtastic_FromRadio_payload_variant_fileInfo_MSGTYPE meshtastic_FileInfo #define meshtastic_FromRadio_payload_variant_clientNotification_MSGTYPE meshtastic_ClientNotification #define meshtastic_FromRadio_payload_variant_deviceuiConfig_MSGTYPE meshtastic_DeviceUIConfig +#define meshtastic_FromRadio_payload_variant_node_info_batch_MSGTYPE meshtastic_NodeInfoBatch #define meshtastic_ClientNotification_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, UINT32, reply_id, 1) \ @@ -2098,6 +2120,7 @@ extern const pb_msgdesc_t meshtastic_StatusMessage_msg; extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg; extern const pb_msgdesc_t meshtastic_MeshPacket_msg; extern const pb_msgdesc_t meshtastic_NodeInfo_msg; +extern const pb_msgdesc_t meshtastic_NodeInfoBatch_msg; extern const pb_msgdesc_t meshtastic_MyNodeInfo_msg; extern const pb_msgdesc_t meshtastic_LogRecord_msg; extern const pb_msgdesc_t meshtastic_QueueStatus_msg; @@ -2133,6 +2156,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg #define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg #define meshtastic_NodeInfo_fields &meshtastic_NodeInfo_msg +#define meshtastic_NodeInfoBatch_fields &meshtastic_NodeInfoBatch_msg #define meshtastic_MyNodeInfo_fields &meshtastic_MyNodeInfo_msg #define meshtastic_LogRecord_fields &meshtastic_LogRecord_msg #define meshtastic_QueueStatus_fields &meshtastic_QueueStatus_msg @@ -2156,9 +2180,11 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_ChunkedPayloadResponse_fields &meshtastic_ChunkedPayloadResponse_msg /* Maximum encoded size of messages (where known) */ +/* meshtastic_NodeInfoBatch_size depends on runtime parameters */ +/* meshtastic_FromRadio_size depends on runtime parameters */ /* meshtastic_resend_chunks_size depends on runtime parameters */ /* meshtastic_ChunkedPayloadResponse_size depends on runtime parameters */ -#define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_FromRadio_size +#define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_ToRadio_size #define meshtastic_ChunkedPayload_size 245 #define meshtastic_ClientNotification_size 482 #define meshtastic_Compressed_size 239 @@ -2166,7 +2192,6 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define meshtastic_DeviceMetadata_size 54 #define meshtastic_DuplicatedPublicKey_size 0 #define meshtastic_FileInfo_size 236 -#define meshtastic_FromRadio_size 510 #define meshtastic_Heartbeat_size 6 #define meshtastic_KeyVerificationFinal_size 65 #define meshtastic_KeyVerificationNumberInform_size 58 diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 3bb4ce817..5bfff5313 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -145,7 +145,7 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread std::mutex toPhoneMutex; std::atomic toPhoneQueueSize{0}; // We use array here (and pay the cost of memcpy) to avoid dynamic memory allocations and frees across FreeRTOS tasks. - std::array, NIMBLE_BLUETOOTH_TO_PHONE_QUEUE_SIZE> toPhoneQueue{}; + std::array, NIMBLE_BLUETOOTH_TO_PHONE_QUEUE_SIZE> toPhoneQueue{}; std::array toPhoneQueueByteSizes{}; // The onReadCallbackIsWaitingForData flag provides synchronization between the NimBLE task's onRead callback and our main // task's runOnce. It's only set by onRead, and only cleared by runOnce. @@ -245,7 +245,7 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread void runOnceHandleToPhoneQueue() { // Stack buffer for getFromRadio packet - uint8_t fromRadioBytes[meshtastic_FromRadio_size] = {0}; + uint8_t fromRadioBytes[MAX_TO_FROM_RADIO_SIZE] = {0}; size_t numBytes = 0; if (onReadCallbackIsWaitingForData || runOnceToPhoneCanPreloadNextPacket()) { @@ -524,7 +524,7 @@ class NimbleBluetoothFromRadioCallback : public NimBLECharacteristicCallbacks } // Pop from toPhoneQueue, protected by toPhoneMutex. Hold the mutex as briefly as possible. - uint8_t fromRadioBytes[meshtastic_FromRadio_size] = {0}; // Stack buffer for getFromRadio packet + uint8_t fromRadioBytes[MAX_TO_FROM_RADIO_SIZE] = {0}; // Stack buffer for getFromRadio packet size_t numBytes = 0; { // scope for toPhoneMutex mutex std::lock_guard guard(bluetoothPhoneAPI->toPhoneMutex); diff --git a/src/platform/nrf52/NRF52Bluetooth.cpp b/src/platform/nrf52/NRF52Bluetooth.cpp index 307e35b0c..5cda552ed 100644 --- a/src/platform/nrf52/NRF52Bluetooth.cpp +++ b/src/platform/nrf52/NRF52Bluetooth.cpp @@ -25,7 +25,7 @@ static BLEDfuSecure bledfusecure; // // This scratch buffer is used for various bluetooth reads/writes - but it is safe because only one bt operation can be in // process at once // static uint8_t trBytes[_max(_max(_max(_max(ToRadio_size, RadioConfig_size), User_size), MyNodeInfo_size), FromRadio_size)]; -static uint8_t fromRadioBytes[meshtastic_FromRadio_size]; +static uint8_t fromRadioBytes[MAX_TO_FROM_RADIO_SIZE]; static uint8_t toRadioBytes[meshtastic_ToRadio_size]; // Last ToRadio value received from the phone