diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 7e65b686..6a0afc19 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 @@ -124,11 +128,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 @@ -161,6 +165,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 +184,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 +// ... _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 @@ -216,7 +224,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; @@ -311,6 +318,58 @@ class MyMesh : public BaseChatMesh { } } + void loadChannels() { + if (_fs->exists("/channels2")) { + File file = _fs->open("/channels2"); + if (file) { + bool full = false; + uint8_t channel_idx = 0; + while (!full) { + ChannelDetails ch; + uint8_t unused[4]; + + bool success = (file.read(unused, 4) == 4); + 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 + + if (setChannel(channel_idx, ch)) { + channel_idx++; + } else { + full = true; + } + } + file.close(); + } + } + } + + void saveChannels() { + #if defined(NRF52_PLATFORM) + File file = _fs->open("/channels2", FILE_O_WRITE); + if (file) { file.seek(0); file.truncate(); } + #else + File file = _fs->open("/channels2", "w", true); + #endif + if (file) { + uint8_t channel_idx = 0; + 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.name, 32) == 32); + success = success && (file.write((uint8_t *) ch.channel.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]; @@ -536,7 +595,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 +772,8 @@ public: _fs->mkdir("/bl"); loadContacts(); - _public = 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); _phy->setSpreadingFactor(_prefs.sf); @@ -769,7 +829,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; @@ -844,12 +906,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 + ChannelDetails channel; + bool success = getChannel(channel_idx, channel); + if (success && txt_type == TXT_TYPE_PLAIN && sendGroupMessage(msg_timestamp, channel.channel, _prefs.node_name, text, len - i)) { writeOKFrame(); } else { writeErrFrame(); @@ -1161,6 +1225,33 @@ 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]; + ChannelDetails channel; + if (getChannel(channel_idx, channel)) { + 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 >= 2+32+32) { + writeErrFrame(); // not supported (yet) + } else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2+32+16) { + uint8_t channel_idx = cmd_frame[1]; + 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(); + } else { + writeErrFrame(); + } } else { writeErrFrame(); MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); @@ -1297,14 +1388,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 #ifdef RAK_4631 @@ -1321,14 +1406,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); diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 7b8dff87..1bb42bda 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 @@ -239,7 +239,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 { @@ -540,6 +542,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 76412d90..bd4564ee 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 @@ -308,7 +308,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 { @@ -572,6 +574,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/examples/simple_secure_chat/main.cpp b/examples/simple_secure_chat/main.cpp index 64e5c321..248353aa 100644 --- a/examples/simple_secure_chat/main.cpp +++ b/examples/simple_secure_chat/main.cpp @@ -111,7 +111,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]; @@ -341,7 +341,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() { @@ -409,7 +409,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/platformio.ini b/platformio.ini index e0ae3ebb..7b91655e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -52,10 +52,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} @@ -80,7 +80,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} @@ -95,7 +95,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 @@ -109,7 +109,6 @@ lib_deps = ${Heltec_lora32_v2.lib_deps} densaugeo/base64 @ ~1.4.0 - ; ================ [Heltec_lora32_v3] extends = esp32_base @@ -127,7 +126,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} @@ -138,10 +137,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} @@ -156,12 +155,12 @@ 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 MESH_PACKET_LOGGING=1 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 [env:Heltec_v3_terminal_chat] @@ -183,7 +182,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 @@ -201,7 +200,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 @@ -222,11 +221,11 @@ 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\"" - -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 @@ -243,10 +242,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} @@ -258,11 +257,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 @@ -271,7 +270,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 @@ -312,11 +311,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 @@ -329,10 +329,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 @@ -357,6 +357,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 @@ -364,10 +365,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 @@ -376,7 +377,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} @@ -390,7 +391,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 @@ -442,10 +443,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 @@ -455,7 +456,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} @@ -470,7 +471,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 @@ -487,7 +488,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 @@ -509,11 +510,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 @@ -538,6 +539,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] @@ -546,10 +548,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 @@ -572,7 +574,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 +590,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 @@ -618,6 +620,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} @@ -626,10 +631,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} @@ -641,11 +646,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 @@ -677,6 +682,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 @@ -684,10 +690,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 @@ -697,11 +703,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 @@ -724,7 +730,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 @@ -740,7 +746,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 @@ -792,7 +798,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 @@ -826,6 +832,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} + + @@ -839,10 +846,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 @@ -852,11 +859,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 @@ -865,7 +872,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 @@ -901,6 +908,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} + + @@ -913,10 +921,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 @@ -925,10 +933,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 @@ -937,7 +945,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..99fd942a 100644 --- a/src/helpers/BaseChatMesh.cpp +++ b/src/helpers/BaseChatMesh.cpp @@ -203,9 +203,9 @@ 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++) { - if (channels[i].hash[0] == hash[0]) { - dest[n++] = channels[i]; + for (int i = 0; i < MAX_GROUP_CHANNELS && n < max_matches; i++) { + if (channels[i].channel.hash[0] == hash[0]) { + dest[n++] = channels[i].channel; } } return n; @@ -588,24 +588,61 @@ 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, ChannelDetails& dest) { + if (idx >= 0 && idx < MAX_GROUP_CHANNELS) { + dest = channels[idx]; + return true; + } + return false; +} +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.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].channel.hash, sizeof(channels[idx].channel.hash), src.channel.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].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* name, const char* psk_base64) { return NULL; // not supported } +bool BaseChatMesh::getChannel(int idx, ChannelDetails& dest) { + return false; +} +bool BaseChatMesh::setChannel(int idx, const ChannelDetails& 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..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,8 +79,8 @@ 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]; - int num_channels; + ChannelDetails channels[MAX_GROUP_CHANNELS]; + int num_channels; // only for addChannel() #endif mesh::Packet* _pendingLoopback; uint8_t temp_buf[MAX_TRANS_UNIT]; @@ -89,6 +94,7 @@ protected: { num_contacts = 0; #ifdef MAX_GROUP_CHANNELS + memset(channels, 0, sizeof(channels)); num_channels = 0; #endif txt_send_timeout = 0; @@ -151,7 +157,10 @@ public: bool addContact(const ContactInfo& contact); int getNumContacts() const { return num_contacts; } ContactsIterator startContactsIterator(); - mesh::GroupChannel* addChannel(const char* psk_base64); + 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(); }; 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 {