From c41f95619bdedb8679ac3613a6981c6c99664b16 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Tue, 26 May 2026 19:22:25 +0100 Subject: [PATCH 1/4] Configurable UART console --- examples/simple_repeater/MyMesh.cpp | 18 +++++++++--------- examples/simple_repeater/main.cpp | 21 ++++++++++++--------- src/MeshCore.h | 10 +++++++--- variants/rak3401/platformio.ini | 2 ++ 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index 1f68c6f2a0..ca31522b35 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -461,10 +461,10 @@ const char *MyMesh::getLogDateTime() { void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) { #if MESH_PACKET_LOGGING - Serial.print(getLogDateTime()); - Serial.print(" RAW: "); - mesh::Utils::printHex(Serial, raw, len); - Serial.println(); + MESH_CONSOLE_SERIAL.print(getLogDateTime()); + MESH_CONSOLE_SERIAL.print(" RAW: "); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, raw, len); + MESH_CONSOLE_SERIAL.println(); #endif } @@ -1043,7 +1043,7 @@ void MyMesh::dumpLogFile() { while (f.available()) { int c = f.read(); if (c < 0) break; - Serial.print((char)c); + MESH_CONSOLE_SERIAL.print((char)c); } f.close(); } @@ -1232,14 +1232,14 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply } } } else if (sender_timestamp == 0 && strcmp(command, "get acl") == 0) { - Serial.println("ACL:"); + MESH_CONSOLE_SERIAL.println("ACL:"); for (int i = 0; i < acl.getNumClients(); i++) { auto c = acl.getClientByIdx(i); if (c->permissions == 0) continue; // skip deleted (or guest) entries - Serial.printf("%02X ", c->permissions); - mesh::Utils::printHex(Serial, c->id.pub_key, PUB_KEY_SIZE); - Serial.printf("\n"); + MESH_CONSOLE_SERIAL.printf("%02X ", c->permissions); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, c->id.pub_key, PUB_KEY_SIZE); + MESH_CONSOLE_SERIAL.printf("\n"); } reply[0] = 0; } else if (memcmp(command, "discover.neighbors", 18) == 0) { diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 297337ab5c..b99ec14572 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -29,7 +29,10 @@ static unsigned long userBtnDownAt = 0; #endif void setup() { - Serial.begin(115200); +#if defined(USE_SERIAL1_CONSOLE) && defined(NRF52_PLATFORM) + ((Uart *)&MESH_CONSOLE_SERIAL)->setPins(PIN_SERIAL1_RX, PIN_SERIAL1_TX); +#endif + MESH_CONSOLE_SERIAL.begin(115200); delay(1000); board.begin(); @@ -86,8 +89,8 @@ void setup() { store.save("_main", the_mesh.self_id); } - Serial.print("Repeater ID: "); - mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println(); + MESH_CONSOLE_SERIAL.print("Repeater ID: "); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, the_mesh.self_id.pub_key, PUB_KEY_SIZE); MESH_CONSOLE_SERIAL.println(); command[0] = 0; @@ -109,12 +112,12 @@ void setup() { void loop() { int len = strlen(command); - while (Serial.available() && len < sizeof(command)-1) { - char c = Serial.read(); + while (MESH_CONSOLE_SERIAL.available() && len < sizeof(command)-1) { + char c = MESH_CONSOLE_SERIAL.read(); if (c != '\n') { command[len++] = c; command[len] = 0; - Serial.print(c); + MESH_CONSOLE_SERIAL.print(c); } if (c == '\r') break; } @@ -123,12 +126,12 @@ void loop() { } if (len > 0 && command[len - 1] == '\r') { // received complete line - Serial.print('\n'); + MESH_CONSOLE_SERIAL.print('\n'); command[len - 1] = 0; // replace newline with C string null terminator char reply[160]; the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial! if (reply[0]) { - Serial.print(" -> "); Serial.println(reply); + MESH_CONSOLE_SERIAL.print(" -> "); MESH_CONSOLE_SERIAL.println(reply); } command[0] = 0; // reset command buffer @@ -141,7 +144,7 @@ void loop() { if (userBtnDownAt == 0) { userBtnDownAt = millis(); } else if ((unsigned long)(millis() - userBtnDownAt) >= USER_BTN_HOLD_OFF_MILLIS) { - Serial.println("Powering off..."); + MESH_CONSOLE_SERIAL.println("Powering off..."); board.powerOff(); // does not return } } else { diff --git a/src/MeshCore.h b/src/MeshCore.h index b4c57faf32..c424481a95 100644 --- a/src/MeshCore.h +++ b/src/MeshCore.h @@ -21,17 +21,21 @@ #define MAX_PATH_SIZE 64 #define MAX_TRANS_UNIT 255 +#ifndef MESH_CONSOLE_SERIAL + #define MESH_CONSOLE_SERIAL Serial +#endif + #if MESH_DEBUG && ARDUINO #include - #define MESH_DEBUG_PRINT(F, ...) Serial.printf("DEBUG: " F, ##__VA_ARGS__) - #define MESH_DEBUG_PRINTLN(F, ...) Serial.printf("DEBUG: " F "\n", ##__VA_ARGS__) + #define MESH_DEBUG_PRINT(F, ...) MESH_CONSOLE_SERIAL.printf("DEBUG: " F, ##__VA_ARGS__) + #define MESH_DEBUG_PRINTLN(F, ...) MESH_CONSOLE_SERIAL.printf("DEBUG: " F "\n", ##__VA_ARGS__) #else #define MESH_DEBUG_PRINT(...) {} #define MESH_DEBUG_PRINTLN(...) {} #endif #if BRIDGE_DEBUG && ARDUINO -#define BRIDGE_DEBUG_PRINTLN(F, ...) Serial.printf("%s BRIDGE: " F, getLogDateTime(), ##__VA_ARGS__) +#define BRIDGE_DEBUG_PRINTLN(F, ...) MESH_CONSOLE_SERIAL.printf("%s BRIDGE: " F, getLogDateTime(), ##__VA_ARGS__) #else #define BRIDGE_DEBUG_PRINTLN(...) {} #endif diff --git a/variants/rak3401/platformio.ini b/variants/rak3401/platformio.ini index 20a8a548b9..1f9472818e 100644 --- a/variants/rak3401/platformio.ini +++ b/variants/rak3401/platformio.ini @@ -36,6 +36,8 @@ build_flags = -D MAX_NEIGHBOURS=50 ;-D MESH_PACKET_LOGGING=1 ;-D MESH_DEBUG=1 + ;-D USE_SERIAL1_CONSOLE + ;-D MESH_CONSOLE_SERIAL=Serial1 build_src_filter = ${rak3401.build_src_filter} + +<../examples/simple_repeater> From 87172fcf294b08f8b5d7cf89c4a173616aaa7efa Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Tue, 26 May 2026 20:21:01 +0100 Subject: [PATCH 2/4] No need to specify Serial1 pins again --- examples/simple_repeater/main.cpp | 3 --- variants/rak3401/platformio.ini | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index b99ec14572..d6ddf9c713 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -29,9 +29,6 @@ static unsigned long userBtnDownAt = 0; #endif void setup() { -#if defined(USE_SERIAL1_CONSOLE) && defined(NRF52_PLATFORM) - ((Uart *)&MESH_CONSOLE_SERIAL)->setPins(PIN_SERIAL1_RX, PIN_SERIAL1_TX); -#endif MESH_CONSOLE_SERIAL.begin(115200); delay(1000); diff --git a/variants/rak3401/platformio.ini b/variants/rak3401/platformio.ini index 1f9472818e..4675a9eebb 100644 --- a/variants/rak3401/platformio.ini +++ b/variants/rak3401/platformio.ini @@ -36,8 +36,8 @@ build_flags = -D MAX_NEIGHBOURS=50 ;-D MESH_PACKET_LOGGING=1 ;-D MESH_DEBUG=1 - ;-D USE_SERIAL1_CONSOLE ;-D MESH_CONSOLE_SERIAL=Serial1 + ;-UENV_INCLUDE_GPS ; GPS is on Serial1, enabling this line disables it build_src_filter = ${rak3401.build_src_filter} + +<../examples/simple_repeater> From f936bc065ba3d3465d0ecba83ecb89f21455c55a Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Sat, 6 Jun 2026 21:52:32 +0100 Subject: [PATCH 3/4] Route remaining console output through MESH_CONSOLE_SERIAL Catch the packet-logging dumps in Dispatcher and the simple_room_server example that were missed when the UART console was made configurable. Co-Authored-By: Claude Opus 4.8 --- examples/simple_room_server/MyMesh.cpp | 18 +++++++++--------- examples/simple_room_server/main.cpp | 17 ++++++++++------- src/Dispatcher.cpp | 20 ++++++++++---------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 2fb80be24c..4fe8bea231 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -201,10 +201,10 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t void MyMesh::logRxRaw(float snr, float rssi, const uint8_t raw[], int len) { #if MESH_PACKET_LOGGING - Serial.print(getLogDateTime()); - Serial.print(" RAW: "); - mesh::Utils::printHex(Serial, raw, len); - Serial.println(); + MESH_CONSOLE_SERIAL.print(getLogDateTime()); + MESH_CONSOLE_SERIAL.print(" RAW: "); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, raw, len); + MESH_CONSOLE_SERIAL.println(); #endif } @@ -789,7 +789,7 @@ void MyMesh::dumpLogFile() { while (f.available()) { int c = f.read(); if (c < 0) break; - Serial.print((char)c); + MESH_CONSOLE_SERIAL.print((char)c); } f.close(); } @@ -918,14 +918,14 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply } } } else if (sender_timestamp == 0 && strcmp(command, "get acl") == 0) { - Serial.println("ACL:"); + MESH_CONSOLE_SERIAL.println("ACL:"); for (int i = 0; i < acl.getNumClients(); i++) { auto c = acl.getClientByIdx(i); if (c->permissions == 0) continue; // skip deleted (or guest) entries - Serial.printf("%02X ", c->permissions); - mesh::Utils::printHex(Serial, c->id.pub_key, PUB_KEY_SIZE); - Serial.printf("\n"); + MESH_CONSOLE_SERIAL.printf("%02X ", c->permissions); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, c->id.pub_key, PUB_KEY_SIZE); + MESH_CONSOLE_SERIAL.printf("\n"); } reply[0] = 0; } else{ diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index a3798b2175..3763f22f9c 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -19,7 +19,10 @@ void halt() { static char command[MAX_POST_TEXT_LEN+1]; void setup() { - Serial.begin(115200); +#if defined(USE_SERIAL1_CONSOLE) && defined(NRF52_PLATFORM) + ((Uart *)&MESH_CONSOLE_SERIAL)->setPins(PIN_SERIAL1_RX, PIN_SERIAL1_TX); +#endif + MESH_CONSOLE_SERIAL.begin(115200); delay(1000); board.begin(); @@ -63,8 +66,8 @@ void setup() { store.save("_main", the_mesh.self_id); } - Serial.print("Room ID: "); - mesh::Utils::printHex(Serial, the_mesh.self_id.pub_key, PUB_KEY_SIZE); Serial.println(); + MESH_CONSOLE_SERIAL.print("Room ID: "); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, the_mesh.self_id.pub_key, PUB_KEY_SIZE); MESH_CONSOLE_SERIAL.println(); command[0] = 0; @@ -86,13 +89,13 @@ void setup() { void loop() { int len = strlen(command); - while (Serial.available() && len < sizeof(command)-1) { - char c = Serial.read(); + while (MESH_CONSOLE_SERIAL.available() && len < sizeof(command)-1) { + char c = MESH_CONSOLE_SERIAL.read(); if (c != '\n') { command[len++] = c; command[len] = 0; } - Serial.print(c); + MESH_CONSOLE_SERIAL.print(c); } if (len == sizeof(command)-1) { // command buffer full command[sizeof(command)-1] = '\r'; @@ -103,7 +106,7 @@ void loop() { char reply[160]; the_mesh.handleCommand(0, command, reply); // NOTE: there is no sender_timestamp via serial! if (reply[0]) { - Serial.print(" -> "); Serial.println(reply); + MESH_CONSOLE_SERIAL.print(" -> "); MESH_CONSOLE_SERIAL.println(reply); } command[0] = 0; // reset command buffer diff --git a/src/Dispatcher.cpp b/src/Dispatcher.cpp index 9d7a11131d..3f4be8ee22 100644 --- a/src/Dispatcher.cpp +++ b/src/Dispatcher.cpp @@ -217,21 +217,21 @@ void Dispatcher::checkRecv() { } if (pkt) { #if MESH_PACKET_LOGGING - Serial.print(getLogDateTime()); - Serial.printf(": RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d time=%d", + MESH_CONSOLE_SERIAL.print(getLogDateTime()); + MESH_CONSOLE_SERIAL.printf(": RX, len=%d (type=%d, route=%s, payload_len=%d) SNR=%d RSSI=%d score=%d time=%d", pkt->getRawLength(), pkt->getPayloadType(), pkt->isRouteDirect() ? "D" : "F", pkt->payload_len, (int)pkt->getSNR(), (int)_radio->getLastRSSI(), (int)(score*1000), air_time); static uint8_t packet_hash[MAX_HASH_SIZE]; pkt->calculatePacketHash(packet_hash); - Serial.print(" hash="); - mesh::Utils::printHex(Serial, packet_hash, MAX_HASH_SIZE); + MESH_CONSOLE_SERIAL.print(" hash="); + mesh::Utils::printHex(MESH_CONSOLE_SERIAL, packet_hash, MAX_HASH_SIZE); if (pkt->getPayloadType() == PAYLOAD_TYPE_PATH || pkt->getPayloadType() == PAYLOAD_TYPE_REQ || pkt->getPayloadType() == PAYLOAD_TYPE_RESPONSE || pkt->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { - Serial.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); + MESH_CONSOLE_SERIAL.printf(" [%02X -> %02X]\n", (uint32_t)pkt->payload[1], (uint32_t)pkt->payload[0]); } else { - Serial.printf("\n"); + MESH_CONSOLE_SERIAL.printf("\n"); } #endif logRx(pkt, pkt->getRawLength(), score); // hook for custom logging @@ -338,14 +338,14 @@ void Dispatcher::checkSend() { outbound_expiry = futureMillis(max_airtime); #if MESH_PACKET_LOGGING - Serial.print(getLogDateTime()); - Serial.printf(": TX, len=%d (type=%d, route=%s, payload_len=%d)", + MESH_CONSOLE_SERIAL.print(getLogDateTime()); + MESH_CONSOLE_SERIAL.printf(": TX, len=%d (type=%d, route=%s, payload_len=%d)", len, outbound->getPayloadType(), outbound->isRouteDirect() ? "D" : "F", outbound->payload_len); if (outbound->getPayloadType() == PAYLOAD_TYPE_PATH || outbound->getPayloadType() == PAYLOAD_TYPE_REQ || outbound->getPayloadType() == PAYLOAD_TYPE_RESPONSE || outbound->getPayloadType() == PAYLOAD_TYPE_TXT_MSG) { - Serial.printf(" [%02X -> %02X]\n", (uint32_t)outbound->payload[1], (uint32_t)outbound->payload[0]); + MESH_CONSOLE_SERIAL.printf(" [%02X -> %02X]\n", (uint32_t)outbound->payload[1], (uint32_t)outbound->payload[0]); } else { - Serial.printf("\n"); + MESH_CONSOLE_SERIAL.printf("\n"); } #endif } From ac0061f3e1d2f308ff13006aa232e001ee2c4747 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Sat, 6 Jun 2026 21:54:25 +0100 Subject: [PATCH 4/4] unslop --- examples/simple_room_server/main.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 3763f22f9c..f08a165f1b 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -19,9 +19,6 @@ void halt() { static char command[MAX_POST_TEXT_LEN+1]; void setup() { -#if defined(USE_SERIAL1_CONSOLE) && defined(NRF52_PLATFORM) - ((Uart *)&MESH_CONSOLE_SERIAL)->setPins(PIN_SERIAL1_RX, PIN_SERIAL1_TX); -#endif MESH_CONSOLE_SERIAL.begin(115200); delay(1000);