WIP: rescue misbranched LXMF and RNode work

This commit is contained in:
liu weikai committed 2026-04-17 10:03:08 +08:00
1 parent 86f71bf705
commit d636eb6398
29 files changed
+6048 -50

No files matched your search

@@ -7,6 +7,7 @@
#include "app/app_config.h"
#include "app/app_facade_access.h"
#include "chat/infra/mesh_protocol_utils.h"
#include "chat/ports/i_mesh_adapter.h"
#include "chat/usecase/contact_service.h"
#include "platform/ui/gps_runtime.h"
#include "platform/ui/screen_runtime.h"
@@ -130,6 +131,36 @@ std::string base_conversation_name(const chat::ConversationId& conv)
return buf;
}
chat::MeshCapabilities active_mesh_capabilities()
{
chat::IMeshAdapter* adapter = app::messagingFacade().getMeshAdapter();
return adapter ? adapter->getCapabilities() : chat::MeshCapabilities{};
}
bool supports_local_text_chat()
{
return active_mesh_capabilities().supports_unicast_text;
}
bool supports_team_chat()
{
return active_mesh_capabilities().supports_unicast_appdata;
}
const char* local_text_chat_unavailable_message()
{
return (active_mesh_protocol() == chat::MeshProtocol::RNode)
? "RNode text chat runs on host"
: "Text chat unavailable";
}
const char* team_chat_unavailable_message()
{
return (active_mesh_protocol() == chat::MeshProtocol::RNode)
? "Team chat unavailable in RNode mode"
: "Team chat unavailable";
}
chat::ConversationId teamConversationId()
{
return chat::ConversationId(kTeamChatChannel, 0, active_mesh_protocol());
@@ -597,7 +628,9 @@ void UiController::switchToConversation(chat::ConversationId conv)
conversation_->setActionCallback(handle_conversation_action, this);
conversation_->setBackCallback(handle_conversation_back, this);
}
const bool can_reply = team_conv_active_ || (conv.protocol == active_mesh_protocol());
const bool can_reply = team_conv_active_
? supports_team_chat()
: (conv.protocol == active_mesh_protocol() && supports_local_text_chat());
conversation_->setReplyEnabled(can_reply);
if (team_conv_active_)
@@ -668,6 +701,16 @@ void UiController::switchToCompose(chat::ConversationId conv)
::ui::SystemNotification::show("Conversation protocol mismatch", 2000);
return;
}
if (!is_team_conv && !supports_local_text_chat())
{
::ui::SystemNotification::show(local_text_chat_unavailable_message(), 2200);
return;
}
if (is_team_conv && !supports_team_chat())
{
::ui::SystemNotification::show(team_chat_unavailable_message(), 2200);
return;
}
state_ = State::Compose;
current_channel_ = conv.channel;
@@ -788,6 +831,11 @@ void UiController::handleSendMessage(const std::string& text)
{
return;
}
if (!supports_local_text_chat())
{
::ui::SystemNotification::show(local_text_chat_unavailable_message(), 2200);
return;
}
service_.sendText(current_channel_, text, current_conv_.peer);
}
@@ -1873,6 +1921,16 @@ void UiController::handleConversationAction(ChatConversationScreen::ActionIntent
::ui::SystemNotification::show("Reply disabled for this protocol", 2000);
return;
}
if (!team_conv_active_ && !supports_local_text_chat())
{
::ui::SystemNotification::show(local_text_chat_unavailable_message(), 2200);
return;
}
if (team_conv_active_ && !supports_team_chat())
{
::ui::SystemNotification::show(team_chat_unavailable_message(), 2200);
return;
}
switchToCompose(current_conv_);
}
}
@@ -316,6 +316,10 @@ static const char* node_protocol_short_label(chat::contacts::NodeProtocolType pr
{
switch (protocol)
{
case chat::contacts::NodeProtocolType::LXMF:
return "LX";
case chat::contacts::NodeProtocolType::RNode:
return "RN";
case chat::contacts::NodeProtocolType::MeshCore:
return "MC";
case chat::contacts::NodeProtocolType::Meshtastic:
@@ -333,6 +337,12 @@ static bool node_protocol_to_mesh(chat::contacts::NodeProtocolType protocol, cha
}
switch (protocol)
{
case chat::contacts::NodeProtocolType::LXMF:
*out = chat::MeshProtocol::LXMF;
return true;
case chat::contacts::NodeProtocolType::RNode:
*out = chat::MeshProtocol::RNode;
return true;
case chat::contacts::NodeProtocolType::MeshCore:
*out = chat::MeshProtocol::MeshCore;
return true;
@@ -375,9 +385,62 @@ static constexpr DiscoveryActionSpec kDiscoveryActionSpecs[] = {
{"Cancel", "Back", DiscoveryActionCommand::Cancel},
};
static chat::MeshCapabilities active_mesh_capabilities()
{
chat::IMeshAdapter* adapter = app::messagingFacade().getMeshAdapter();
return adapter ? adapter->getCapabilities() : chat::MeshCapabilities{};
}
static bool supports_local_text_chat()
{
return active_mesh_capabilities().supports_unicast_text;
}
static bool supports_team_chat()
{
return active_mesh_capabilities().supports_unicast_appdata;
}
static const char* local_text_chat_unavailable_message()
{
return (active_mesh_protocol() == chat::MeshProtocol::RNode)
? "RNode text chat runs on host"
: "Text chat unavailable";
}
static const char* team_chat_unavailable_message()
{
return (active_mesh_protocol() == chat::MeshProtocol::RNode)
? "Team chat unavailable in RNode mode"
: "Team chat unavailable";
}
static const char* broadcast_chat_unavailable_message(const BroadcastTargetSpec& spec)
{
if (spec.protocol == chat::MeshProtocol::Meshtastic)
{
return "MT send uses slot 0/1 only";
}
if (spec.protocol == chat::MeshProtocol::RNode)
{
return "RNode text chat runs on host";
}
return "Chat unavailable";
}
static size_t get_broadcast_target_count()
{
return (active_mesh_protocol() == chat::MeshProtocol::Meshtastic) ? 8U : 2U;
switch (active_mesh_protocol())
{
case chat::MeshProtocol::Meshtastic:
return 8U;
case chat::MeshProtocol::MeshCore:
return 2U;
case chat::MeshProtocol::RNode:
return 1U;
default:
return 0U;
}
}
static bool get_broadcast_target_spec(int index, BroadcastTargetSpec* out)
@@ -403,6 +466,20 @@ static bool get_broadcast_target_spec(int index, BroadcastTargetSpec* out)
return true;
}
if (active_mesh_protocol() == chat::MeshProtocol::RNode)
{
if (index != 0)
{
return false;
}
out->protocol = chat::MeshProtocol::RNode;
out->channel = chat::ChannelId::PRIMARY;
out->channel_index = 0;
out->enabled = true;
out->chat_supported = false;
return true;
}
switch (index)
{
case 0:
@@ -432,6 +509,10 @@ static std::string format_broadcast_target_label(const BroadcastTargetSpec& spec
snprintf(buf, sizeof(buf), "[MT] Slot %u", static_cast<unsigned>(spec.channel_index));
return std::string(buf);
}
if (spec.protocol == chat::MeshProtocol::RNode)
{
return "[RN] Modem Bridge";
}
return (spec.channel == chat::ChannelId::SECONDARY) ? "[MC] Secondary" : "[MC] Primary";
}
@@ -453,6 +534,10 @@ static std::string format_broadcast_target_status(const BroadcastTargetSpec& spe
}
return spec.chat_supported ? "Ready" : "Slot";
}
if (spec.protocol == chat::MeshProtocol::RNode)
{
return "Host bridge";
}
return "Ready";
}
@@ -736,7 +821,7 @@ static void on_list_item_clicked(lv_event_t* e)
BroadcastTargetSpec spec{};
if (get_selected_broadcast_target(&spec, nullptr) && !spec.chat_supported)
{
::ui::SystemNotification::show("MT send uses slot 0/1 only", 2200);
::ui::SystemNotification::show(broadcast_chat_unavailable_message(spec), 2200);
return;
}
}
@@ -1225,7 +1310,7 @@ static void open_chat_compose()
}
if (!target_spec.chat_supported)
{
::ui::SystemNotification::show("MT send uses slot 0/1 only", 2200);
::ui::SystemNotification::show(broadcast_chat_unavailable_message(target_spec), 2200);
return;
}
protocol = target_spec.protocol;
@@ -1235,6 +1320,11 @@ static void open_chat_compose()
}
else if (g_contacts_state.current_mode == ContactsMode::Team)
{
if (!supports_team_chat())
{
::ui::SystemNotification::show(team_chat_unavailable_message(), 2200);
return;
}
channel = chat::ChannelId::PRIMARY;
peer_id = 0;
title = team::ui::g_team_state.team_name.empty()
@@ -1243,6 +1333,11 @@ static void open_chat_compose()
}
else
{
if (!supports_local_text_chat())
{
::ui::SystemNotification::show(local_text_chat_unavailable_message(), 2200);
return;
}
channel = chat::ChannelId::PRIMARY;
peer_id = node->node_id;
chat::MeshProtocol node_protocol = protocol;
@@ -1251,7 +1346,7 @@ static void open_chat_compose()
{
char buf[64];
snprintf(buf, sizeof(buf), "Switch to %s to chat",
(node_protocol == chat::MeshProtocol::MeshCore) ? "MeshCore" : "Meshtastic");
chat::infra::meshProtocolName(node_protocol));
::ui::SystemNotification::show(buf, 2200);
return;
}
@@ -1531,6 +1626,13 @@ static void on_compose_action(chat::ui::ChatComposeScreen::ActionIntent intent,
return;
}
if (!supports_local_text_chat())
{
::ui::SystemNotification::show(local_text_chat_unavailable_message(), 2200);
close_chat_compose();
return;
}
std::string text = g_contacts_state.compose_screen->getText();
if (!text.empty())
{
@@ -2155,7 +2257,9 @@ static void open_action_menu_modal()
(g_contacts_state.current_mode == ContactsMode::Contacts ||
g_contacts_state.current_mode == ContactsMode::Nearby);
int action_count = 2; // Chat + Cancel
const bool allow_chat_action =
(g_contacts_state.current_mode == ContactsMode::Team) ? supports_team_chat() : supports_local_text_chat();
int action_count = allow_chat_action ? 2 : 1; // Chat + Cancel
if (g_contacts_state.current_mode == ContactsMode::Contacts)
{
action_count += 3; // Edit/Delete/Info
@@ -2255,7 +2359,10 @@ static void open_action_menu_modal()
}
};
add_action(ActionMenuCommand::Chat, "Chat");
if (allow_chat_action)
{
add_action(ActionMenuCommand::Chat, "Chat");
}
if (g_contacts_state.current_mode == ContactsMode::Contacts)
{
add_action(ActionMenuCommand::Edit, "Edit");
@@ -2324,7 +2431,7 @@ void refresh_ui()
lv_obj_clear_flag(g_contacts_state.sub_container, LV_OBJ_FLAG_SCROLLABLE);
}
bool team_available = is_team_available();
bool team_available = is_team_available() && supports_team_chat();
const bool meshcore_mode = (active_mesh_protocol() == chat::MeshProtocol::MeshCore);
if (g_contacts_state.team_btn)
{
@@ -2450,7 +2557,11 @@ void refresh_ui()
target.display_name = format_broadcast_target_label(spec);
target.protocol = (spec.protocol == chat::MeshProtocol::MeshCore)
? chat::contacts::NodeProtocolType::MeshCore
: chat::contacts::NodeProtocolType::Meshtastic;
: ((spec.protocol == chat::MeshProtocol::LXMF)
? chat::contacts::NodeProtocolType::LXMF
: ((spec.protocol == chat::MeshProtocol::RNode)
? chat::contacts::NodeProtocolType::RNode
: chat::contacts::NodeProtocolType::Meshtastic));
target.channel = spec.channel_index;
broadcast_list.push_back(target);
}
@@ -7,6 +7,7 @@
#include "app/app_config.h"
#include "app/app_facade_access.h"
#include "chat/domain/chat_types.h"
#include "chat/infra/mesh_protocol_utils.h"
#include "chat/infra/meshtastic/mt_region.h"
#include "ui/components/info_card.h"
#include "ui/components/two_pane_layout.h"
@@ -51,7 +52,33 @@ void format_contacts_title(char* out, size_t out_len)
snprintf(out, out_len, "Contacts (MeshCore)");
return;
}
snprintf(out, out_len, "Contacts");
if (protocol == chat::MeshProtocol::RNode)
{
const chat::MeshConfig& rnode = app_ctx.getConfig().rnode_config;
if (rnode.override_frequency_mhz > 0.0f)
{
snprintf(out, out_len, "Contacts (RNode - %.3fMHz)", rnode.override_frequency_mhz);
}
else
{
snprintf(out, out_len, "Contacts (RNode)");
}
return;
}
if (protocol == chat::MeshProtocol::LXMF)
{
const chat::MeshConfig& lxmf = app_ctx.getConfig().rnode_config;
if (lxmf.override_frequency_mhz > 0.0f)
{
snprintf(out, out_len, "Contacts (LXMF - %.3fMHz)", lxmf.override_frequency_mhz);
}
else
{
snprintf(out, out_len, "Contacts (LXMF)");
}
return;
}
snprintf(out, out_len, "Contacts (%s)", chat::infra::meshProtocolName(protocol));
}
} // namespace
@@ -2,6 +2,8 @@
#if defined(ARDUINO) || defined(ESP_PLATFORM)
#include "app/app_config.h"
#include "app/app_facade_access.h"
#include "platform/ui/hostlink_runtime.h"
#include "ui/app_runtime.h"
#include "ui/assets/fonts/fonts.h"
@@ -37,8 +39,42 @@ void request_exit()
ui_request_exit_to_menu();
}
bool use_rnode_bridge()
{
return app::appFacade().getConfig().mesh_protocol == chat::MeshProtocol::RNode;
}
const char* page_title()
{
return use_rnode_bridge() ? "RNode Bridge" : "Data Exchange";
}
const char* page_subtitle()
{
return use_rnode_bridge() ? "USB CDC KISS modem for Reticulum" : "Data Exchange";
}
const char* status_text(platform::ui::hostlink::LinkState state)
{
if (use_rnode_bridge())
{
switch (state)
{
case platform::ui::hostlink::LinkState::Stopped:
case platform::ui::hostlink::LinkState::Waiting:
return "Waiting for Reticulum host...";
case platform::ui::hostlink::LinkState::Connected:
case platform::ui::hostlink::LinkState::Handshaking:
return "Host connected, probing modem...";
case platform::ui::hostlink::LinkState::Ready:
return "RNode modem ready";
case platform::ui::hostlink::LinkState::Error:
return "Bridge error";
default:
return "Waiting for Reticulum host...";
}
}
switch (state)
{
case platform::ui::hostlink::LinkState::Stopped:
@@ -133,7 +169,7 @@ void enter(const shell::Host* host, lv_obj_t* parent)
lv_obj_add_event_cb(s_root, root_key_event_cb, LV_EVENT_KEY, nullptr);
::ui::widgets::top_bar_init(s_top_bar, s_root);
::ui::widgets::top_bar_set_title(s_top_bar, "Data Exchange");
::ui::widgets::top_bar_set_title(s_top_bar, page_title());
::ui::widgets::top_bar_set_back_callback(s_top_bar, on_back, nullptr);
if (s_top_bar.back_btn)
{
@@ -173,7 +209,7 @@ void enter(const shell::Host* host, lv_obj_t* parent)
lv_obj_center(stack);
lv_obj_t* title = lv_label_create(stack);
lv_label_set_text(title, "Data Exchange");
lv_label_set_text(title, page_subtitle());
lv_obj_set_style_text_font(title, &lv_font_montserrat_18, 0);
s_status_label = lv_label_create(stack);
@@ -11,6 +11,7 @@
#include "app/app_facade_access.h"
#include "board/BoardBase.h"
#include "chat/domain/chat_types.h"
#include "chat/infra/mesh_protocol_utils.h"
#include "chat/infra/meshcore/mc_region_presets.h"
#include "chat/infra/meshtastic/mt_region.h"
#include "meshtastic/config.pb.h"
@@ -399,12 +400,31 @@ static bool parse_float_text(const char* text, float* out_value)
return true;
}
static chat::MeshProtocol selected_protocol()
{
return static_cast<chat::MeshProtocol>(g_settings.chat_protocol);
}
static bool is_meshcore_protocol_selected()
{
return selected_protocol() == chat::MeshProtocol::MeshCore;
}
static bool is_rnode_protocol_selected()
{
return selected_protocol() == chat::MeshProtocol::RNode ||
selected_protocol() == chat::MeshProtocol::LXMF;
}
static void reset_mesh_settings()
{
app::IAppFacade& app_ctx = app::appFacade();
app_ctx.getConfig().meshtastic_config = chat::MeshConfig();
app_ctx.getConfig().meshtastic_config.region = app::AppConfig::kDefaultRegionCode;
app_ctx.getConfig().meshcore_config = chat::MeshConfig();
app_ctx.getConfig().applyMeshCoreFactoryDefaults();
app_ctx.getConfig().rnode_config = chat::MeshConfig();
app_ctx.getConfig().applyRNodeFactoryDefaults();
strncpy(app_ctx.getConfig().meshcore_config.meshcore_channel_name, "Public",
sizeof(app_ctx.getConfig().meshcore_config.meshcore_channel_name) - 1);
app_ctx.getConfig().meshcore_config.meshcore_channel_name[sizeof(app_ctx.getConfig().meshcore_config.meshcore_channel_name) - 1] = '\0';
@@ -417,12 +437,9 @@ static void reset_mesh_settings()
g_settings.chat_psk[0] = '\0';
g_settings.net_use_preset = app_ctx.getConfig().meshtastic_config.use_preset;
g_settings.net_modem_preset = app_ctx.getConfig().meshtastic_config.modem_preset;
g_settings.net_tx_power = app_ctx.getConfig().meshtastic_config.tx_power;
g_settings.net_tx_power = app_ctx.getConfig().activeMeshConfig().tx_power;
g_settings.net_hop_limit = app_ctx.getConfig().meshtastic_config.hop_limit;
const chat::MeshConfig& active_cfg =
(app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::MeshCore)
? app_ctx.getConfig().meshcore_config
: app_ctx.getConfig().meshtastic_config;
const chat::MeshConfig& active_cfg = app_ctx.getConfig().activeMeshConfig();
g_settings.net_tx_enabled = active_cfg.tx_enabled;
g_settings.net_relay = app_ctx.getConfig().meshtastic_config.enable_relay;
g_settings.net_duty_cycle = true;
@@ -576,12 +593,20 @@ static void settings_load()
const app::AppConfig& cfg = app_ctx.getConfig();
const chat::MeshConfig& mt_cfg = cfg.meshtastic_config;
const chat::MeshConfig& mc_cfg = cfg.meshcore_config;
const chat::MeshConfig& rn_cfg = cfg.rnode_config;
g_settings.chat_region = mt_cfg.region;
g_settings.chat_channel = cfg.chat_channel;
const uint8_t* active_psk =
(cfg.mesh_protocol == chat::MeshProtocol::MeshCore) ? mc_cfg.secondary_key : mt_cfg.secondary_key;
if (is_zero_key(active_psk, sizeof(mt_cfg.secondary_key)))
const uint8_t* active_psk = nullptr;
if (cfg.mesh_protocol == chat::MeshProtocol::MeshCore)
{
active_psk = mc_cfg.secondary_key;
}
else if (cfg.mesh_protocol == chat::MeshProtocol::Meshtastic)
{
active_psk = mt_cfg.secondary_key;
}
if (!active_psk || is_zero_key(active_psk, sizeof(mt_cfg.secondary_key)))
{
g_settings.chat_psk[0] = '\0';
}
@@ -593,24 +618,38 @@ static void settings_load()
sizeof(g_settings.chat_psk));
}
g_settings.net_use_preset = mt_cfg.use_preset;
g_settings.net_modem_preset = mt_cfg.modem_preset;
g_settings.net_manual_bw = static_cast<int>(std::lround(mt_cfg.bandwidth_khz));
g_settings.net_manual_sf = mt_cfg.spread_factor;
g_settings.net_manual_cr = mt_cfg.coding_rate;
int tx_power = mt_cfg.tx_power;
if (cfg.mesh_protocol == chat::MeshProtocol::RNode ||
cfg.mesh_protocol == chat::MeshProtocol::LXMF)
{
g_settings.net_use_preset = 0;
g_settings.net_modem_preset = 0;
g_settings.net_manual_bw = static_cast<int>(std::lround(rn_cfg.bandwidth_khz));
g_settings.net_manual_sf = rn_cfg.spread_factor;
g_settings.net_manual_cr = rn_cfg.coding_rate;
float_to_text(rn_cfg.override_frequency_mhz, g_settings.net_override_freq,
sizeof(g_settings.net_override_freq), 3);
}
else
{
g_settings.net_use_preset = mt_cfg.use_preset;
g_settings.net_modem_preset = mt_cfg.modem_preset;
g_settings.net_manual_bw = static_cast<int>(std::lround(mt_cfg.bandwidth_khz));
g_settings.net_manual_sf = mt_cfg.spread_factor;
g_settings.net_manual_cr = mt_cfg.coding_rate;
float_to_text(mt_cfg.override_frequency_mhz, g_settings.net_override_freq,
sizeof(g_settings.net_override_freq), 3);
}
int tx_power = cfg.activeMeshConfig().tx_power;
if (tx_power < kNetTxPowerMin) tx_power = kNetTxPowerMin;
if (tx_power > kNetTxPowerMax) tx_power = kNetTxPowerMax;
g_settings.net_tx_power = tx_power;
g_settings.net_hop_limit = mt_cfg.hop_limit;
g_settings.net_tx_enabled = (cfg.mesh_protocol == chat::MeshProtocol::MeshCore)
? mc_cfg.tx_enabled
: mt_cfg.tx_enabled;
g_settings.net_tx_enabled = cfg.activeMeshConfig().tx_enabled;
g_settings.net_override_duty_cycle = mt_cfg.override_duty_cycle;
g_settings.net_channel_num = mt_cfg.channel_num;
g_settings.net_relay = mt_cfg.enable_relay;
float_to_text(mt_cfg.frequency_offset_mhz, g_settings.net_freq_offset, sizeof(g_settings.net_freq_offset), 3);
float_to_text(mt_cfg.override_frequency_mhz, g_settings.net_override_freq, sizeof(g_settings.net_override_freq), 3);
g_settings.net_duty_cycle = cfg.net_duty_cycle;
g_settings.net_channel_util = cfg.net_channel_util;
@@ -900,7 +939,15 @@ static void on_text_save_clicked(lv_event_t* e)
modal_close();
return;
}
app_ctx.getConfig().meshtastic_config.override_frequency_mhz = value;
if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.override_frequency_mhz = value;
}
else
{
app_ctx.getConfig().meshtastic_config.override_frequency_mhz = value;
}
app_ctx.saveConfig();
app_ctx.applyMeshConfig();
}
@@ -1169,10 +1216,18 @@ static void on_option_clicked(lv_event_t* e)
if (payload->item->pref_key && strcmp(payload->item->pref_key, "net_bw") == 0)
{
app::IAppFacade& app_ctx = app::appFacade();
app_ctx.getConfig().meshtastic_config.bandwidth_khz = static_cast<float>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.bandwidth_khz = static_cast<float>(payload->value);
}
else
{
app_ctx.getConfig().meshtastic_config.bandwidth_khz = static_cast<float>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
}
app_ctx.saveConfig();
app_ctx.applyMeshConfig();
rebuild_list = true;
@@ -1180,10 +1235,18 @@ static void on_option_clicked(lv_event_t* e)
if (payload->item->pref_key && strcmp(payload->item->pref_key, "net_sf") == 0)
{
app::IAppFacade& app_ctx = app::appFacade();
app_ctx.getConfig().meshtastic_config.spread_factor = static_cast<uint8_t>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.spread_factor = static_cast<uint8_t>(payload->value);
}
else
{
app_ctx.getConfig().meshtastic_config.spread_factor = static_cast<uint8_t>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
}
app_ctx.saveConfig();
app_ctx.applyMeshConfig();
rebuild_list = true;
@@ -1191,10 +1254,18 @@ static void on_option_clicked(lv_event_t* e)
if (payload->item->pref_key && strcmp(payload->item->pref_key, "net_cr") == 0)
{
app::IAppFacade& app_ctx = app::appFacade();
app_ctx.getConfig().meshtastic_config.coding_rate = static_cast<uint8_t>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.coding_rate = static_cast<uint8_t>(payload->value);
}
else
{
app_ctx.getConfig().meshtastic_config.coding_rate = static_cast<uint8_t>(payload->value);
app_ctx.getConfig().meshtastic_config.use_preset = false;
g_settings.net_use_preset = false;
prefs_put_int("net_use_preset", 0);
}
app_ctx.saveConfig();
app_ctx.applyMeshConfig();
rebuild_list = true;
@@ -1322,7 +1393,15 @@ static void on_option_clicked(lv_event_t* e)
if (payload->item->pref_key && strcmp(payload->item->pref_key, "net_tx_power") == 0)
{
app::IAppFacade& app_ctx = app::appFacade();
app_ctx.getConfig().meshtastic_config.tx_power = static_cast<int8_t>(payload->value);
if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.tx_power = static_cast<int8_t>(payload->value);
}
else
{
app_ctx.getConfig().meshtastic_config.tx_power = static_cast<int8_t>(payload->value);
}
app_ctx.saveConfig();
app_ctx.applyMeshConfig();
}
@@ -1607,6 +1686,8 @@ static const settings::ui::SettingOption kChatChannelOptions[] = {
static const settings::ui::SettingOption kChatProtocolOptions[] = {
{"Meshtastic", static_cast<int>(chat::MeshProtocol::Meshtastic)},
{"MeshCore", static_cast<int>(chat::MeshProtocol::MeshCore)},
{"LXMF", static_cast<int>(chat::MeshProtocol::LXMF)},
{"RNode Bridge", static_cast<int>(chat::MeshProtocol::RNode)},
};
static const settings::ui::SettingOption kNetPresetOptions[] = {
@@ -1801,7 +1882,7 @@ static settings::ui::SettingItem kMapItems[] = {
static settings::ui::SettingItem kChatItems[] = {
{"User Name", settings::ui::SettingType::Text, nullptr, 0, nullptr, nullptr, g_settings.user_name, sizeof(g_settings.user_name), false, "chat_user"},
{"Short Name", settings::ui::SettingType::Text, nullptr, 0, nullptr, nullptr, g_settings.short_name, sizeof(g_settings.short_name), false, "chat_short"},
{"Protocol", settings::ui::SettingType::Enum, kChatProtocolOptions, 2, &g_settings.chat_protocol, nullptr, nullptr, 0, false, "mesh_protocol"},
{"Protocol", settings::ui::SettingType::Enum, kChatProtocolOptions, 4, &g_settings.chat_protocol, nullptr, nullptr, 0, false, "mesh_protocol"},
{"Region", settings::ui::SettingType::Enum, kChatRegionOptions, 0, &g_settings.chat_region, nullptr, nullptr, 0, false, "chat_region"},
{"Channel", settings::ui::SettingType::Enum, kChatChannelOptions, 2, &g_settings.chat_channel, nullptr, nullptr, 0, false, "chat_channel"},
{"Channel Key / PSK", settings::ui::SettingType::Text, nullptr, 0, nullptr, nullptr, g_settings.chat_psk, sizeof(g_settings.chat_psk), true, "chat_psk"},
@@ -1954,7 +2035,8 @@ static bool should_show_item(const settings::ui::SettingItem& item)
return true;
}
const bool meshcore = (g_settings.chat_protocol == static_cast<int>(chat::MeshProtocol::MeshCore));
const bool meshcore = is_meshcore_protocol_selected();
const bool rnode = is_rnode_protocol_selected();
// Relay is currently not implemented as real forwarding in Meshtastic path.
if (has_pref_key(item, "net_relay"))
@@ -1986,6 +2068,38 @@ static bool should_show_item(const settings::ui::SettingItem& item)
if (has_pref_key(item, "net_freq_offset")) return false;
if (has_pref_key(item, "net_override_freq")) return false;
}
else if (rnode)
{
if (has_pref_key(item, "chat_region")) return false;
if (has_pref_key(item, "chat_channel")) return false;
if (has_pref_key(item, "chat_psk")) return false;
if (has_pref_key(item, "privacy_encrypt")) return false;
if (has_pref_key(item, "privacy_pki")) return false;
if (has_pref_key(item, "net_use_preset")) return false;
if (has_pref_key(item, "net_preset")) return false;
if (has_pref_key(item, "net_hop_limit")) return false;
if (has_pref_key(item, "net_override_duty")) return false;
if (has_pref_key(item, "net_channel_num")) return false;
if (has_pref_key(item, "net_freq_offset")) return false;
if (has_pref_key(item, "net_duty_cycle")) return false;
if (has_pref_key(item, "net_util")) return false;
if (has_pref_key(item, "mc_region_preset")) return false;
if (has_pref_key(item, "mc_freq")) return false;
if (has_pref_key(item, "mc_bw")) return false;
if (has_pref_key(item, "mc_sf")) return false;
if (has_pref_key(item, "mc_cr")) return false;
if (has_pref_key(item, "mc_tx_power")) return false;
if (has_pref_key(item, "mc_repeat")) return false;
if (has_pref_key(item, "mc_rx_delay")) return false;
if (has_pref_key(item, "mc_airtime")) return false;
if (has_pref_key(item, "mc_flood_max")) return false;
if (has_pref_key(item, "mc_multi_acks")) return false;
if (has_pref_key(item, "mc_channel_slot")) return false;
if (has_pref_key(item, "mc_channel_name")) return false;
if (has_pref_key(item, "mc_channel_key")) return false;
}
else
{
if (has_pref_key(item, "mc_region_preset")) return false;
@@ -2149,6 +2263,11 @@ static bool activate_item_widget(settings::ui::ItemWidget& widget)
{
app_ctx.getConfig().meshcore_config.tx_enabled = *item.bool_value;
}
else if (app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::RNode ||
app_ctx.getConfig().mesh_protocol == chat::MeshProtocol::LXMF)
{
app_ctx.getConfig().rnode_config.tx_enabled = *item.bool_value;
}
else
{
app_ctx.getConfig().meshtastic_config.tx_enabled = *item.bool_value;