From de3f11d16c3be61205cdeebbf48d336c623d9169 Mon Sep 17 00:00:00 2001 From: recrof Date: Sun, 9 Mar 2025 22:57:31 +0100 Subject: [PATCH 1/8] - Enabled sx1262 boosted RX gain for all supported radios - Made quoted -D flags more readable --- platformio.ini | 104 ++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 48 deletions(-) diff --git a/platformio.ini b/platformio.ini index 20e2802b..a203e807 100644 --- a/platformio.ini +++ b/platformio.ini @@ -50,10 +50,10 @@ build_src_filter = ${esp32_base.build_src_filter} extends = Heltec_lora32_v2 build_flags = ${Heltec_lora32_v2.build_flags} - -D ADVERT_NAME="\"Heltec Repeater\"" + -D ADVERT_NAME='"Heltec Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v2.build_src_filter} @@ -107,7 +107,6 @@ lib_deps = ${Heltec_lora32_v2.lib_deps} densaugeo/base64 @ ~1.4.0 - ; ================ [Heltec_lora32_v3] extends = esp32_base @@ -125,7 +124,7 @@ build_flags = -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! - -D SX126X_RX_BOOSTED_GAIN=true + -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${esp32_base.build_src_filter} lib_deps = ${esp32_base.lib_deps} @@ -136,10 +135,10 @@ extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME="\"Heltec Repeater\"" + -D ADVERT_NAME='"Heltec Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} @@ -154,11 +153,11 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} build_flags = ${Heltec_lora32_v3.build_flags} -D DISPLAY_CLASS=SSD1306Display - -D ADVERT_NAME="\"Heltec Room\"" + -D ADVERT_NAME='"Heltec Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -223,8 +222,8 @@ build_flags = -D MAX_GROUP_CHANNELS=1 -D DISPLAY_CLASS=SSD1306Display -D WIFI_DEBUG_LOGGING=1 - -D WIFI_SSID="\"myssid\"" - -D WIFI_PWD="\"mypwd\"" + -D WIFI_SSID='"myssid"' + -D WIFI_PWD='"mypwd"' ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 ; -D MESH_PACKET_LOGGING=1 @@ -241,10 +240,10 @@ lib_deps = extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} - -D ADVERT_NAME="\"Heltec Repeater\"" + -D ADVERT_NAME='"Heltec Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} @@ -256,11 +255,11 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_room_server> build_flags = ${Heltec_lora32_v3.build_flags} - -D ADVERT_NAME="\"Heltec Room\"" + -D ADVERT_NAME='"Heltec Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -310,11 +309,12 @@ build_flags = ${Xiao_esp32_C3.build_flags} -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper + -D SX126X_RX_BOOSTED_GAIN=1 -D LORA_TX_POWER=22 - -D ADVERT_NAME="\"Xiao Repeater\"" + -D ADVERT_NAME='"Xiao Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -327,10 +327,10 @@ build_flags = -D RADIO_CLASS=CustomSX1268 -D WRAPPER_CLASS=CustomSX1268Wrapper -D LORA_TX_POWER=22 - -D ADVERT_NAME="\"Xiao Repeater\"" + -D ADVERT_NAME='"Xiao Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -355,6 +355,7 @@ build_flags = ${esp32_base.build_flags} -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 [env:Xiao_S3_WIO_Repeater] extends = Xiao_S3_WIO @@ -362,10 +363,10 @@ build_src_filter = ${Xiao_S3_WIO.build_src_filter} +<../examples/simple_repeater/main.cpp> build_flags = ${Xiao_S3_WIO.build_flags} - -D ADVERT_NAME="\"XiaoS3 Repeater\"" + -D ADVERT_NAME='"XiaoS3 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -440,10 +441,10 @@ build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} +<../examples/simple_repeater> build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} - -D ADVERT_NAME="\"TLora-V2.1-1.6 Repeater\"" + -D ADVERT_NAME='"TLora-V2.1-1.6 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 ; -D CORE_DEBUG_LEVEL=3 @@ -507,11 +508,11 @@ build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} +<../examples/simple_room_server> build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} - -D ADVERT_NAME="\"TLora-V2.1-1.6 Room\"" + -D ADVERT_NAME='"TLora-V2.1-1.6 Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -536,6 +537,7 @@ build_flags = ${esp32_base.build_flags} -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 ; === LilyGo T3S3 with SX1262 environments === [env:LilyGo_T3S3_sx1262_Repeater] @@ -544,10 +546,10 @@ build_src_filter = ${LilyGo_T3S3_sx1262.build_src_filter} +<../examples/simple_repeater/main.cpp> build_flags = ${LilyGo_T3S3_sx1262.build_flags} - -D ADVERT_NAME="\"T3S3-1262 Repeater\"" + -D ADVERT_NAME='"T3S3-1262 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -616,6 +618,9 @@ build_flags = -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! +; -D SX126X_RX_BOOSTED_GAIN=1 - DO NOT ENABLE THIS! +; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance + build_src_filter = ${esp32_base.build_src_filter} lib_deps = ${esp32_base.lib_deps} @@ -624,10 +629,10 @@ lib_deps = extends = Station_G2 build_flags = ${Station_G2.build_flags} - -D ADVERT_NAME="\"Station G2 Repeater\"" + -D ADVERT_NAME='"Station G2 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Station_G2.build_src_filter} @@ -639,11 +644,11 @@ build_src_filter = ${Station_G2.build_src_filter} +<../examples/simple_room_server> build_flags = ${Station_G2.build_flags} - -D ADVERT_NAME="\"Station G2 Room\"" + -D ADVERT_NAME='"Station G2 Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -675,6 +680,7 @@ build_flags = ${nrf52840_base.build_flags} -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 [env:RAK_4631_Repeater] extends = rak4631 @@ -682,10 +688,10 @@ build_src_filter = ${rak4631.build_src_filter} +<../examples/simple_repeater/main.cpp> build_flags = ${rak4631.build_flags} - -D ADVERT_NAME="\"RAK4631 Repeater\"" + -D ADVERT_NAME='"RAK4631 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -695,11 +701,11 @@ build_src_filter = ${rak4631.build_src_filter} +<../examples/simple_room_server/main.cpp> build_flags = ${rak4631.build_flags} - -D ADVERT_NAME="\"Test Room\"" + -D ADVERT_NAME='"Test Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -823,6 +829,7 @@ build_flags = ${nrf52840_t114.build_flags} -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${nrf52840_t114.build_src_filter} + + @@ -836,10 +843,10 @@ build_src_filter = ${Heltec_t114.build_src_filter} +<../examples/simple_repeater/main.cpp> build_flags = ${Heltec_t114.build_flags} - -D ADVERT_NAME="\"Heltec_T114 Repeater\"" + -D ADVERT_NAME='"Heltec_T114 Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -849,11 +856,11 @@ build_src_filter = ${Heltec_t114.build_src_filter} +<../examples/simple_room_server> build_flags = ${Heltec_t114.build_flags} - -D ADVERT_NAME="\"Heltec_T114 Room\"" + -D ADVERT_NAME='"Heltec_T114 Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" - -D ROOM_PASSWORD="\"hello\"" + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -898,6 +905,7 @@ build_flags = ${nrf52840_techo.build_flags} -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 -D SX126X_CURRENT_LIMIT=130 + -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = ${nrf52840_techo.build_src_filter} + + @@ -910,10 +918,10 @@ extends = LilyGo_Techo build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_repeater/main.cpp> build_flags = ${LilyGo_Techo.build_flags} - -D ADVERT_NAME="\"T-Echo Repeater\"" + -D ADVERT_NAME='"T-Echo Repeater"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 @@ -922,10 +930,10 @@ extends = LilyGo_Techo build_src_filter = ${LilyGo_Techo.build_src_filter} +<../examples/simple_room_server/main.cpp> build_flags = ${LilyGo_Techo.build_flags} - -D ADVERT_NAME="\"T-Echo Room\"" + -D ADVERT_NAME='"T-Echo Room"' -D ADVERT_LAT=-37.0 -D ADVERT_LON=145.0 - -D ADMIN_PASSWORD="\"password\"" + -D ADMIN_PASSWORD='"password"' ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 From 5c72969e2c47169c1f223a62ddf3d81b2b2c207b Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 10 Mar 2025 23:28:19 +1100 Subject: [PATCH 2/8] * repeater & room server: new CLI config "flood.max" --- examples/simple_repeater/main.cpp | 5 ++++- examples/simple_room_server/main.cpp | 5 ++++- src/helpers/CommonCLI.cpp | 13 +++++++++++++ src/helpers/CommonCLI.h | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 5743647b..605e7a35 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -235,7 +235,9 @@ protected: } bool allowPacketForward(const mesh::Packet* packet) override { - return !_prefs.disable_fwd; + if (_prefs.disable_fwd) return false; + if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false; + return true; } const char* getLogDateTime() override { @@ -536,6 +538,7 @@ public: _prefs.cr = LORA_CR; _prefs.tx_power_dbm = LORA_TX_POWER; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs + _prefs.flood_max = 64; } CommonCLI* getCLI() { return &_cli; } diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 285d59c6..573ff1a4 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -304,7 +304,9 @@ protected: } bool allowPacketForward(const mesh::Packet* packet) override { - return !_prefs.disable_fwd; + if (_prefs.disable_fwd) return false; + if (packet->isRouteFlood() && packet->path_len >= _prefs.flood_max) return false; + return true; } void onAnonDataRecv(mesh::Packet* packet, uint8_t type, const mesh::Identity& sender, uint8_t* data, size_t len) override { @@ -568,6 +570,7 @@ public: _prefs.tx_power_dbm = LORA_TX_POWER; _prefs.disable_fwd = 1; _prefs.advert_interval = 1; // default to 2 minutes for NEW installs + _prefs.flood_max = 64; #ifdef ROOM_PASSWORD StrHelper::strncpy(_prefs.guest_password, ROOM_PASSWORD, sizeof(_prefs.guest_password)); #endif diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 21cd690f..30777b4b 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -41,6 +41,7 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) { file.read((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.read((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.read(pad, 4); // 120 + file.read((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -91,6 +92,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) { file.write((uint8_t *) &_prefs->reserved2, sizeof(_prefs->reserved2)); // 115 file.write((uint8_t *) &_prefs->bw, sizeof(_prefs->bw)); // 116 file.write(pad, 4); // 120 + file.write((uint8_t *) &_prefs->flood_max, sizeof(_prefs->flood_max)); // 124 file.close(); } @@ -176,6 +178,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch sprintf(reply, "> %s", StrHelper::ftoa(_prefs->rx_delay_base)); } else if (memcmp(config, "txdelay", 7) == 0) { sprintf(reply, "> %s", StrHelper::ftoa(_prefs->tx_delay_factor)); + } else if (memcmp(config, "flood.max", 9) == 0) { + sprintf(reply, "> %d", (uint32_t)_prefs->flood_max); } else if (memcmp(config, "direct.txdelay", 14) == 0) { sprintf(reply, "> %s", StrHelper::ftoa(_prefs->direct_tx_delay_factor)); } else if (memcmp(config, "tx", 2) == 0 && (config[2] == 0 || config[2] == ' ')) { @@ -262,6 +266,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch } else { strcpy(reply, "Error, cannot be negative"); } + } else if (memcmp(config, "flood.max ", 10) == 0) { + uint8_t m = atoi(&config[10]); + if (m <= 64) { + _prefs->flood_max = m; + savePrefs(); + strcpy(reply, "OK"); + } else { + strcpy(reply, "Error, max 64"); + } } else if (memcmp(config, "direct.txdelay ", 15) == 0) { float f = atof(&config[15]); if (f >= 0) { diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index ec038d07..5538f339 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -23,6 +23,7 @@ struct NodePrefs { // persisted to file uint8_t reserved1; uint8_t reserved2; float bw; + uint8_t flood_max; }; class CommonCLICallbacks { From f9b2428dcd9963fd0a2956df01ea8349cc15baa2 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 11 Mar 2025 13:25:48 +1100 Subject: [PATCH 3/8] * BLE_NAME_PREFIX refactor --- examples/companion_radio/main.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 29ec7028..35600de1 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -46,6 +46,10 @@ #define OFFLINE_QUEUE_SIZE 16 #endif +#ifndef BLE_NAME_PREFIX + #define BLE_NAME_PREFIX "MeshCore-" +#endif + #include #define SEND_TIMEOUT_BASE_MILLIS 500 @@ -1286,14 +1290,8 @@ void setup() { the_mesh.begin(InternalFS, trng); #ifdef BLE_PIN_CODE - char dev_name[32+10]; - const char* prefix = - #ifdef BLE_NAME_PREFIX - BLE_NAME_PREFIX; - #else - "MeshCore-"; - #endif - sprintf(dev_name, "%s%s", prefix, the_mesh.getNodeName()); + char dev_name[32+16]; + sprintf(dev_name, "%s%s", BLE_NAME_PREFIX, the_mesh.getNodeName()); serial_interface.begin(dev_name, the_mesh.getBLEPin()); #else pinMode(WB_IO2, OUTPUT); @@ -1308,14 +1306,8 @@ void setup() { WiFi.begin(WIFI_SSID, WIFI_PWD); serial_interface.begin(TCP_PORT); #elif defined(BLE_PIN_CODE) - char dev_name[32+10]; - const char* prefix = - #ifdef BLE_NAME_PREFIX - BLE_NAME_PREFIX; - #else - "MeshCore-"; - #endif - sprintf(dev_name, "%s%s", prefix, the_mesh.getNodeName()); + char dev_name[32+16]; + sprintf(dev_name, "%s%s", BLE_NAME_PREFIX, the_mesh.getNodeName()); serial_interface.begin(dev_name, the_mesh.getBLEPin()); #else serial_interface.begin(Serial); From 8c68dbb6e95b56970e6d451c58f316d22d180fd6 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 11 Mar 2025 14:50:40 +1100 Subject: [PATCH 4/8] * Companion: new CMD_GET_CHANNEL, CMD_SET_CHANNEL --- examples/companion_radio/main.cpp | 37 ++++++++++++++++++++++++++---- platformio.ini | 36 ++++++++++++++--------------- src/helpers/BaseChatMesh.cpp | 38 ++++++++++++++++++++++++++++++- src/helpers/BaseChatMesh.h | 6 ++++- 4 files changed, 92 insertions(+), 25 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 35600de1..c8178b25 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -161,6 +161,8 @@ static uint32_t _atoi(const char* sp) { #define CMD_HAS_CONNECTION 28 #define CMD_LOGOUT 29 // 'Disconnect' #define CMD_GET_CONTACT_BY_KEY 30 +#define CMD_GET_CHANNEL 31 +#define CMD_SET_CHANNEL 32 #define RESP_CODE_OK 0 #define RESP_CODE_ERR 1 @@ -178,6 +180,7 @@ static uint32_t _atoi(const char* sp) { #define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY #define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY #define RESP_CODE_DISABLED 15 +#define RESP_CODE_CHANNEL_INFO 16 // a reply to CMD_GET_CHANNEL // these are _pushed_ to client app at any time #define PUSH_CODE_ADVERT 0x80 @@ -216,7 +219,6 @@ class MyMesh : public BaseChatMesh { uint32_t expected_ack_crc; // TODO: keep table of expected ACKs uint32_t pending_login; uint32_t pending_status; - mesh::GroupChannel* _public; BaseSerialInterface* _serial; unsigned long last_msg_sent; ContactsIterator _iter; @@ -536,7 +538,7 @@ protected: void onChannelMessageRecv(const mesh::GroupChannel& channel, int in_path_len, uint32_t timestamp, const char *text) override { int i = 0; out_frame[i++] = RESP_CODE_CHANNEL_MSG_RECV; - out_frame[i++] = 0; // FUTURE: channel_idx (will just be 'public' for now) + out_frame[i++] = findChannelIdx(channel); out_frame[i++] = in_path_len < 0 ? 0xFF : in_path_len; out_frame[i++] = TXT_TYPE_PLAIN; memcpy(&out_frame[i], ×tamp, 4); i += 4; @@ -713,7 +715,7 @@ public: _fs->mkdir("/bl"); loadContacts(); - _public = addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel + addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel _phy->setFrequency(_prefs.freq); _phy->setSpreadingFactor(_prefs.sf); @@ -844,12 +846,14 @@ public: } else if (cmd_frame[0] == CMD_SEND_CHANNEL_TXT_MSG) { // send GroupChannel msg int i = 1; uint8_t txt_type = cmd_frame[i++]; // should be TXT_TYPE_PLAIN - uint8_t channel_idx = cmd_frame[i++]; // reserved future + uint8_t channel_idx = cmd_frame[i++]; uint32_t msg_timestamp; memcpy(&msg_timestamp, &cmd_frame[i], 4); i += 4; const char *text = (char *) &cmd_frame[i]; - if (txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, *_public, _prefs.node_name, text, len - i)) { // hard-coded to 'public' channel for now + mesh::GroupChannel channel; + bool success = getChannel(channel_idx, channel); + if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel, _prefs.node_name, text, len - i)) { writeOKFrame(); } else { writeErrFrame(); @@ -1161,6 +1165,29 @@ public: uint8_t* pub_key = &cmd_frame[1]; stopConnection(pub_key); writeOKFrame(); + } else if (cmd_frame[0] == CMD_GET_CHANNEL && len >= 2) { + uint8_t channel_idx = cmd_frame[1]; + mesh::GroupChannel channel; + if (getChannel(channel_idx, channel)) { + out_frame[0] = RESP_CODE_CHANNEL_INFO; + out_frame[1] = channel_idx; + memcpy(&out_frame[2], channel.secret, 16); // NOTE: only 128-bit supported + _serial->writeFrame(out_frame, 2 + 16); + } else { + writeErrFrame(); + } + } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+32) { + writeErrFrame(); // not supported (yet) + } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+16) { + uint8_t channel_idx = cmd_frame[1]; + mesh::GroupChannel channel; + memset(channel.secret, 0, sizeof(channel.secret)); + memcpy(channel.secret, &cmd_frame[2], 16); // NOTE: only 128-bit supported + if (setChannel(channel_idx, channel)) { + writeOKFrame(); + } else { + writeErrFrame(); + } } else { writeErrFrame(); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); diff --git a/platformio.ini b/platformio.ini index 6175206f..07ffbf91 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,7 +78,7 @@ extends = Heltec_lora32_v2 build_flags = ${Heltec_lora32_v2.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 ; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v2.build_src_filter} @@ -93,7 +93,7 @@ extends = Heltec_lora32_v2 build_flags = ${Heltec_lora32_v2.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -180,7 +180,7 @@ extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 @@ -198,7 +198,7 @@ extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display -D BLE_PIN_CODE=0 ; dynamic, random PIN -D BLE_DEBUG_LOGGING=1 @@ -219,7 +219,7 @@ extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display -D WIFI_DEBUG_LOGGING=1 -D WIFI_SSID='"myssid"' @@ -268,7 +268,7 @@ extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -375,7 +375,7 @@ extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_S3_WIO.build_src_filter} @@ -389,7 +389,7 @@ extends = Xiao_S3_WIO build_flags = ${Xiao_S3_WIO.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -454,7 +454,7 @@ extends = LilyGo_TLora_V2_1_1_6 build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${LilyGo_TLora_V2_1_1_6.build_src_filter} @@ -469,7 +469,7 @@ extends = LilyGo_TLora_V2_1_1_6 build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 @@ -486,7 +486,7 @@ extends = LilyGo_TLora_V2_1_1_6 build_flags = ${LilyGo_TLora_V2_1_1_6.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 ; -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -572,7 +572,7 @@ extends = LilyGo_T3S3_sx1262 build_flags = ${LilyGo_T3S3_sx1262.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 @@ -588,7 +588,7 @@ extends = LilyGo_T3S3_sx1262 build_flags = ${LilyGo_T3S3_sx1262.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -728,7 +728,7 @@ extends = rak4631 build_flags = ${rak4631.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 ; -D ENABLE_PRIVATE_KEY_EXPORT=1 ; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 @@ -744,7 +744,7 @@ extends = rak4631 build_flags = ${rak4631.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -796,7 +796,7 @@ upload_protocol = nrfutil extends = t1000-e build_flags = ${t1000-e.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D MESH_PACKET_LOGGING=1 @@ -870,7 +870,7 @@ extends = Heltec_t114 build_flags = ${Heltec_t114.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 @@ -943,7 +943,7 @@ extends = LilyGo_Techo build_flags = ${LilyGo_Techo.build_flags} -D MAX_CONTACTS=100 - -D MAX_GROUP_CHANNELS=1 + -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 ; -D ENABLE_PRIVATE_KEY_IMPORT=1 diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index e8e48e53..e44ffcf3 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -203,7 +203,7 @@ void BaseChatMesh::onAckRecv(mesh::Packet* packet, uint32_t ack_crc) { #ifdef MAX_GROUP_CHANNELS int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel dest[], int max_matches) { int n = 0; - for (int i = 0; i < num_channels && n < max_matches; i++) { + for (int i = 0; i < MAX_GROUP_CHANNELS && n < max_matches; i++) { if (channels[i].hash[0] == hash[0]) { dest[n++] = channels[i]; } @@ -602,10 +602,46 @@ mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) { } return NULL; } +bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) { + if (idx >= 0 && idx < MAX_GROUP_CHANNELS) { + dest = channels[idx]; + return true; + } + return false; +} +bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) { + static uint8_t zeroes[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + if (idx >= 0 && idx < MAX_GROUP_CHANNELS) { + channels[idx] = src; + if (memcmp(&src.secret[16], zeroes, 16) == 0) { + mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 16); // 128-bit key + } else { + mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 32); // 256-bit key + } + return true; + } + return false; +} +int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) { + for (int i = 0; i < MAX_GROUP_CHANNELS; i++) { + if (memcmp(ch.secret, channels[i].secret, sizeof(ch.secret)) == 0) return i; + } + return -1; // not found +} #else mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) { return NULL; // not supported } +bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) { + return false; +} +bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) { + return false; +} +int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) { + return -1; // not found +} #endif ContactsIterator BaseChatMesh::startContactsIterator() { diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index 0f2e0283..c5b60dd1 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -75,7 +75,7 @@ class BaseChatMesh : public mesh::Mesh { unsigned long txt_send_timeout; #ifdef MAX_GROUP_CHANNELS mesh::GroupChannel channels[MAX_GROUP_CHANNELS]; - int num_channels; + int num_channels; // only for addChannel() #endif mesh::Packet* _pendingLoopback; uint8_t temp_buf[MAX_TRANS_UNIT]; @@ -89,6 +89,7 @@ protected: { num_contacts = 0; #ifdef MAX_GROUP_CHANNELS + memset(channels, 0, sizeof(channels)); num_channels = 0; #endif txt_send_timeout = 0; @@ -152,6 +153,9 @@ public: int getNumContacts() const { return num_contacts; } ContactsIterator startContactsIterator(); mesh::GroupChannel* addChannel(const char* psk_base64); + bool getChannel(int idx, mesh::GroupChannel& dest); + bool setChannel(int idx, const mesh::GroupChannel& src); + int findChannelIdx(const mesh::GroupChannel& ch); void loop(); }; From adf9b24867ee296ae1f7921b8f26e464d0fb0140 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 11 Mar 2025 15:31:38 +1100 Subject: [PATCH 5/8] * companion: channels now persisted. RESP_CODE_DEVICE_INFO now includes MAX_CONTACTS (div 2) and MAX_GROUP_CHANNELS --- examples/companion_radio/main.cpp | 59 +++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index c8178b25..c0b98c7b 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -180,7 +180,8 @@ static uint32_t _atoi(const char* sp) { #define RESP_CODE_DEVICE_INFO 13 // a reply to CMD_DEVICE_QEURY #define RESP_CODE_PRIVATE_KEY 14 // a reply to CMD_EXPORT_PRIVATE_KEY #define RESP_CODE_DISABLED 15 -#define RESP_CODE_CHANNEL_INFO 16 // a reply to CMD_GET_CHANNEL +// ... _V3 stuff in here +#define RESP_CODE_CHANNEL_INFO 18 // a reply to CMD_GET_CHANNEL // these are _pushed_ to client app at any time #define PUSH_CODE_ADVERT 0x80 @@ -313,6 +314,56 @@ class MyMesh : public BaseChatMesh { } } + void loadChannels() { + if (_fs->exists("/channels")) { + File file = _fs->open("/channels"); + if (file) { + bool full = false; + uint8_t channel_idx = 0; + while (!full) { + mesh::GroupChannel ch; + uint8_t unused[4]; + + bool success = (file.read(unused, 4) == 4); + success = success && (file.read((uint8_t *) ch.secret, 32) == 32); + + if (!success) break; // EOF + + if (setChannel(channel_idx, ch)) { + channel_idx++; + } else { + full = true; + } + } + file.close(); + } + } + } + + void saveChannels() { + #if defined(NRF52_PLATFORM) + File file = _fs->open("/channels", FILE_O_WRITE); + if (file) { file.seek(0); file.truncate(); } + #else + File file = _fs->open("/channels", "w", true); + #endif + if (file) { + uint8_t channel_idx = 0; + mesh::GroupChannel ch; + uint8_t unused[4]; + memset(unused, 0, 4); + + while (getChannel(channel_idx, ch)) { + bool success = (file.write(unused, 4) == 4); + success = success && (file.write((uint8_t *) ch.secret, 32) == 32); + + if (!success) break; // write failed + channel_idx++; + } + file.close(); + } + } + int getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]) override { char path[64]; char fname[18]; @@ -716,6 +767,7 @@ public: loadContacts(); addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel + loadChannels(); _phy->setFrequency(_prefs.freq); _phy->setSpreadingFactor(_prefs.sf); @@ -771,7 +823,9 @@ public: int i = 0; out_frame[i++] = RESP_CODE_DEVICE_INFO; out_frame[i++] = FIRMWARE_VER_CODE; - memset(&out_frame[i], 0, 6); i += 6; // reserved + out_frame[i++] = MAX_CONTACTS / 2; // v3+ + out_frame[i++] = MAX_GROUP_CHANNELS; // v3+ + memset(&out_frame[i], 0, 4); i += 4; // reserved memset(&out_frame[i], 0, 12); strcpy((char *) &out_frame[i], FIRMWARE_BUILD_DATE); i += 12; StrHelper::strzcpy((char *) &out_frame[i], board.getManufacturerName(), 40); i += 40; @@ -1184,6 +1238,7 @@ public: memset(channel.secret, 0, sizeof(channel.secret)); memcpy(channel.secret, &cmd_frame[2], 16); // NOTE: only 128-bit supported if (setChannel(channel_idx, channel)) { + saveChannels(); writeOKFrame(); } else { writeErrFrame(); From b94fed4e4e9bd9cf50dc5ab45b1794ab4086a93b Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Tue, 11 Mar 2025 17:58:12 +1100 Subject: [PATCH 6/8] * companion: channel names --- examples/companion_radio/main.cpp | 47 +++++++++++++++------------- examples/simple_secure_chat/main.cpp | 6 ++-- src/helpers/BaseChatMesh.cpp | 31 +++++++++--------- src/helpers/BaseChatMesh.h | 13 +++++--- 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index c0b98c7b..05a8c58d 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -315,17 +315,18 @@ class MyMesh : public BaseChatMesh { } void loadChannels() { - if (_fs->exists("/channels")) { - File file = _fs->open("/channels"); + if (_fs->exists("/channels2")) { + File file = _fs->open("/channels2"); if (file) { bool full = false; uint8_t channel_idx = 0; while (!full) { - mesh::GroupChannel ch; + ChannelDetails ch; uint8_t unused[4]; bool success = (file.read(unused, 4) == 4); - success = success && (file.read((uint8_t *) ch.secret, 32) == 32); + success = success && (file.read((uint8_t *) ch.name, 32) == 32); + success = success && (file.read((uint8_t *) ch.channel.secret, 32) == 32); if (!success) break; // EOF @@ -342,20 +343,21 @@ class MyMesh : public BaseChatMesh { void saveChannels() { #if defined(NRF52_PLATFORM) - File file = _fs->open("/channels", FILE_O_WRITE); + File file = _fs->open("/channels2", FILE_O_WRITE); if (file) { file.seek(0); file.truncate(); } #else - File file = _fs->open("/channels", "w", true); + File file = _fs->open("/channels2", "w", true); #endif if (file) { uint8_t channel_idx = 0; - mesh::GroupChannel ch; + ChannelDetails ch; uint8_t unused[4]; memset(unused, 0, 4); while (getChannel(channel_idx, ch)) { bool success = (file.write(unused, 4) == 4); - success = success && (file.write((uint8_t *) ch.secret, 32) == 32); + success = success && (file.write((uint8_t *) ch.name, 32) == 32); + success = success && (file.write((uint8_t *) ch.channel.secret, 32) == 32); if (!success) break; // write failed channel_idx++; @@ -766,7 +768,7 @@ public: _fs->mkdir("/bl"); loadContacts(); - addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel + addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel loadChannels(); _phy->setFrequency(_prefs.freq); @@ -905,9 +907,9 @@ public: memcpy(&msg_timestamp, &cmd_frame[i], 4); i += 4; const char *text = (char *) &cmd_frame[i]; - mesh::GroupChannel channel; + ChannelDetails channel; bool success = getChannel(channel_idx, channel); - if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel, _prefs.node_name, text, len - i)) { + if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel.channel, _prefs.node_name, text, len - i)) { writeOKFrame(); } else { writeErrFrame(); @@ -1221,22 +1223,25 @@ public: writeOKFrame(); } else if (cmd_frame[0] == CMD_GET_CHANNEL && len >= 2) { uint8_t channel_idx = cmd_frame[1]; - mesh::GroupChannel channel; + ChannelDetails channel; if (getChannel(channel_idx, channel)) { - out_frame[0] = RESP_CODE_CHANNEL_INFO; - out_frame[1] = channel_idx; - memcpy(&out_frame[2], channel.secret, 16); // NOTE: only 128-bit supported - _serial->writeFrame(out_frame, 2 + 16); + int i = 0; + out_frame[i++] = RESP_CODE_CHANNEL_INFO; + out_frame[i++] = channel_idx; + strcpy((char *)&out_frame[i], channel.name); i += 32; + memcpy(&out_frame[i], channel.channel.secret, 16); i += 16; // NOTE: only 128-bit supported + _serial->writeFrame(out_frame, i); } else { writeErrFrame(); } - } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+32) { + } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2+32+32) { writeErrFrame(); // not supported (yet) - } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 3+16) { + } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2+32+16) { uint8_t channel_idx = cmd_frame[1]; - mesh::GroupChannel channel; - memset(channel.secret, 0, sizeof(channel.secret)); - memcpy(channel.secret, &cmd_frame[2], 16); // NOTE: only 128-bit supported + ChannelDetails channel; + StrHelper::strncpy(channel.name, (char *) &cmd_frame[2], 32); + memset(channel.channel.secret, 0, sizeof(channel.channel.secret)); + memcpy(channel.channel.secret, &cmd_frame[2+32], 16); // NOTE: only 128-bit supported if (setChannel(channel_idx, channel)) { saveChannels(); writeOKFrame(); diff --git a/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 951d51dc..3a376e54 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -107,7 +107,7 @@ class MyMesh : public BaseChatMesh, ContactVisitor { FILESYSTEM* _fs; NodePrefs _prefs; uint32_t expected_ack_crc; - mesh::GroupChannel* _public; + ChannelDetails* _public; unsigned long last_msg_sent; ContactInfo* curr_recipient; char command[512+10]; @@ -337,7 +337,7 @@ public: } loadContacts(); - _public = addChannel(PUBLIC_GROUP_PSK); // pre-configure Andy's public channel + _public = addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel } void savePrefs() { @@ -405,7 +405,7 @@ public: temp[5 + MAX_TEXT_LEN] = 0; // truncate if too long int len = strlen((char *) &temp[5]); - auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_TXT, *_public, temp, 5 + len); + auto pkt = createGroupDatagram(PAYLOAD_TYPE_GRP_TXT, _public->channel, temp, 5 + len); if (pkt) { sendFlood(pkt); Serial.println(" Sent."); diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index e44ffcf3..f49c5364 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -204,8 +204,8 @@ void BaseChatMesh::onAckRecv(mesh::Packet* packet, uint32_t ack_crc) { int BaseChatMesh::searchChannelsByHash(const uint8_t* hash, mesh::GroupChannel dest[], int max_matches) { int n = 0; for (int i = 0; i < MAX_GROUP_CHANNELS && n < max_matches; i++) { - if (channels[i].hash[0] == hash[0]) { - dest[n++] = channels[i]; + if (channels[i].channel.hash[0] == hash[0]) { + dest[n++] = channels[i].channel; } } return n; @@ -588,36 +588,37 @@ bool BaseChatMesh::removeContact(ContactInfo& contact) { #ifdef MAX_GROUP_CHANNELS #include -mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) { +ChannelDetails* BaseChatMesh::addChannel(const char* name, const char* psk_base64) { if (num_channels < MAX_GROUP_CHANNELS) { auto dest = &channels[num_channels]; - memset(dest->secret, 0, sizeof(dest->secret)); - int len = decode_base64((unsigned char *) psk_base64, strlen(psk_base64), dest->secret); + memset(dest->channel.secret, 0, sizeof(dest->channel.secret)); + int len = decode_base64((unsigned char *) psk_base64, strlen(psk_base64), dest->channel.secret); if (len == 32 || len == 16) { - mesh::Utils::sha256(dest->hash, sizeof(dest->hash), dest->secret, len); + mesh::Utils::sha256(dest->channel.hash, sizeof(dest->channel.hash), dest->channel.secret, len); + StrHelper::strncpy(dest->name, name, sizeof(dest->name)); num_channels++; return dest; } } return NULL; } -bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) { +bool BaseChatMesh::getChannel(int idx, ChannelDetails& dest) { if (idx >= 0 && idx < MAX_GROUP_CHANNELS) { dest = channels[idx]; return true; } return false; } -bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) { +bool BaseChatMesh::setChannel(int idx, const ChannelDetails& src) { static uint8_t zeroes[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; if (idx >= 0 && idx < MAX_GROUP_CHANNELS) { channels[idx] = src; - if (memcmp(&src.secret[16], zeroes, 16) == 0) { - mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 16); // 128-bit key + if (memcmp(&src.channel.secret[16], zeroes, 16) == 0) { + mesh::Utils::sha256(channels[idx].channel.hash, sizeof(channels[idx].channel.hash), src.channel.secret, 16); // 128-bit key } else { - mesh::Utils::sha256(channels[idx].hash, sizeof(channels[idx].hash), src.secret, 32); // 256-bit key + mesh::Utils::sha256(channels[idx].channel.hash, sizeof(channels[idx].channel.hash), src.channel.secret, 32); // 256-bit key } return true; } @@ -625,18 +626,18 @@ bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) { } int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) { for (int i = 0; i < MAX_GROUP_CHANNELS; i++) { - if (memcmp(ch.secret, channels[i].secret, sizeof(ch.secret)) == 0) return i; + if (memcmp(ch.secret, channels[i].channel.secret, sizeof(ch.secret)) == 0) return i; } return -1; // not found } #else -mesh::GroupChannel* BaseChatMesh::addChannel(const char* psk_base64) { +ChannelDetails* BaseChatMesh::addChannel(const char* psk_base64) { return NULL; // not supported } -bool BaseChatMesh::getChannel(int idx, mesh::GroupChannel& dest) { +bool BaseChatMesh::getChannel(int idx, ChannelDetails& dest) { return false; } -bool BaseChatMesh::setChannel(int idx, const mesh::GroupChannel& src) { +bool BaseChatMesh::setChannel(int idx, const ChannelDetails& src) { return false; } int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) { diff --git a/src/helpers/BaseChatMesh.h b/src/helpers/BaseChatMesh.h index c5b60dd1..ec603a7e 100644 --- a/src/helpers/BaseChatMesh.h +++ b/src/helpers/BaseChatMesh.h @@ -61,6 +61,11 @@ struct ConnectionInfo { uint32_t expected_ack; }; +struct ChannelDetails { + mesh::GroupChannel channel; + char name[32]; +}; + /** * \brief abstract Mesh class for common 'chat' client */ @@ -74,7 +79,7 @@ class BaseChatMesh : public mesh::Mesh { int matching_peer_indexes[MAX_SEARCH_RESULTS]; unsigned long txt_send_timeout; #ifdef MAX_GROUP_CHANNELS - mesh::GroupChannel channels[MAX_GROUP_CHANNELS]; + ChannelDetails channels[MAX_GROUP_CHANNELS]; int num_channels; // only for addChannel() #endif mesh::Packet* _pendingLoopback; @@ -152,9 +157,9 @@ public: bool addContact(const ContactInfo& contact); int getNumContacts() const { return num_contacts; } ContactsIterator startContactsIterator(); - mesh::GroupChannel* addChannel(const char* psk_base64); - bool getChannel(int idx, mesh::GroupChannel& dest); - bool setChannel(int idx, const mesh::GroupChannel& src); + ChannelDetails* addChannel(const char* name, const char* psk_base64); + bool getChannel(int idx, ChannelDetails& dest); + bool setChannel(int idx, const ChannelDetails& src); int findChannelIdx(const mesh::GroupChannel& ch); void loop(); From 38b9834261eda606231e70ef684bd007dcb0fbef Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Thu, 13 Mar 2025 13:32:46 +1100 Subject: [PATCH 7/8] * missing param --- src/helpers/BaseChatMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/BaseChatMesh.cpp b/src/helpers/BaseChatMesh.cpp index f49c5364..99fd942a 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -631,7 +631,7 @@ int BaseChatMesh::findChannelIdx(const mesh::GroupChannel& ch) { return -1; // not found } #else -ChannelDetails* BaseChatMesh::addChannel(const char* psk_base64) { +ChannelDetails* BaseChatMesh::addChannel(const char* name, const char* psk_base64) { return NULL; // not supported } bool BaseChatMesh::getChannel(int idx, ChannelDetails& dest) { From 658094f654f48bb569412d64b4d4d195eda248bd Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Thu, 13 Mar 2025 13:46:01 +1100 Subject: [PATCH 8/8] * ver bump: 1.3.0 --- examples/companion_radio/main.cpp | 4 ++-- examples/simple_repeater/main.cpp | 4 ++-- examples/simple_room_server/main.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 05a8c58d..f3374ecb 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -124,11 +124,11 @@ static uint32_t _atoi(const char* sp) { #define FIRMWARE_VER_CODE 2 #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "9 Mar 2025" + #define FIRMWARE_BUILD_DATE "13 Mar 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.2.2" + #define FIRMWARE_VERSION "v1.3.0" #endif #define CMD_APP_START 1 diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 605e7a35..0ddf4fdf 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "9 Mar 2025" + #define FIRMWARE_BUILD_DATE "13 Mar 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.2.2" + #define FIRMWARE_VERSION "v1.3.0" #endif #ifndef LORA_FREQ diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 573ff1a4..94d1e4fc 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "9 Mar 2025" + #define FIRMWARE_BUILD_DATE "13 Mar 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.2.2" + #define FIRMWARE_VERSION "v1.3.0" #endif #ifndef LORA_FREQ