diff --git a/modules/ui_shared/src/ui/menu/dashboard/dashboard_mesh_widget.cpp b/modules/ui_shared/src/ui/menu/dashboard/dashboard_mesh_widget.cpp index 2076e6ab..8121aeff 100644 --- a/modules/ui_shared/src/ui/menu/dashboard/dashboard_mesh_widget.cpp +++ b/modules/ui_shared/src/ui/menu/dashboard/dashboard_mesh_widget.cpp @@ -5,6 +5,7 @@ #include #include "app/app_facade_access.h" +#include "ble/ble_manager.h" #include "platform/ui/device_runtime.h" #include "ui/menu/dashboard/dashboard_state.h" #include "ui/screens/team/team_ui_store.h" diff --git a/modules/ui_shared/src/ui/ui_status.cpp b/modules/ui_shared/src/ui/ui_status.cpp index cc7c878f..76d68336 100644 --- a/modules/ui_shared/src/ui/ui_status.cpp +++ b/modules/ui_shared/src/ui/ui_status.cpp @@ -7,6 +7,7 @@ #include "app/app_config.h" #include "app/app_facade_access.h" +#include "ble/ble_manager.h" #include "chat/usecase/chat_service.h" #include "platform/ui/gps_runtime.h" #include "platform/ui/tracker_runtime.h" diff --git a/platform/nrf52/arduino_common/src/ble/meshtastic_ble.cpp b/platform/nrf52/arduino_common/src/ble/meshtastic_ble.cpp index 0dedeaff..6252d4f3 100644 --- a/platform/nrf52/arduino_common/src/ble/meshtastic_ble.cpp +++ b/platform/nrf52/arduino_common/src/ble/meshtastic_ble.cpp @@ -2,7 +2,6 @@ #include "app/app_config.h" #include "ble/ble_uuids.h" -#include "ble/bluefruit_runtime.h" #if defined(GAT562_MESH_EVB_PRO) #include "boards/gat562_mesh_evb_pro/settings_store.h" #endif @@ -356,7 +355,10 @@ void onSecured(uint16_t conn_handle) void prepareBluefruit(const std::string& device_name) { bleLogBoth("[BLE][nrf52][mt] bluefruit begin name=%s", device_name.c_str()); - ::ble::bluefruit_runtime::ensureInitialized(device_name.c_str()); + Bluefruit.autoConnLed(false); + Bluefruit.configPrphBandwidth(BANDWIDTH_MAX); + Bluefruit.begin(); + Bluefruit.setName(device_name.c_str()); Bluefruit.Periph.setConnectCallback(onBleConnect); Bluefruit.Periph.setDisconnectCallback(onBleDisconnect); bleLogBoth("[BLE][nrf52][mt] bluefruit ready"); @@ -423,6 +425,12 @@ void onFromRadioAuthorize(uint16_t conn_handle, BLECharacteristic* chr, ble_gatt return; } + bleLogBoth("[BLE][nrf52][mt][auth] conn=%u offset=%u chr=%p svc=%p", + static_cast(conn_handle), + static_cast(request->offset), + static_cast(chr), + static_cast(s_active_service)); + if (request->offset == 0) { if (s_active_service && s_active_service->hasReadableFromRadio()) @@ -479,7 +487,7 @@ MeshtasticBleService::MeshtasticBleService(app::IAppBleFacade& ctx, const std::s persisted.has_module ? 1U : 0U); #if defined(GAT562_MESH_EVB_PRO) - bleLogBoth("[BLE][nrf52][mt] settings_store load_status=%s last_save_status=%s", + bleLogBoth("[BLE][nrf52][mt] settings_store load=%s save=%s", ::boards::gat562_mesh_evb_pro::settings_store::statusLabel( ::boards::gat562_mesh_evb_pro::settings_store::lastLoadStatus()), ::boards::gat562_mesh_evb_pro::settings_store::statusLabel( @@ -549,69 +557,58 @@ void MeshtasticBleService::start() prepareBluefruit(device_name_); applyBleSecurity(); - if (!gatt_initialized_) + service_.begin(); + bleLogBoth("[BLE][nrf52][mt] service begin"); + + to_radio_.setProperties(CHR_PROPS_WRITE); + to_radio_.setPermission(SECMODE_OPEN, SECMODE_OPEN); + to_radio_.setFixedLen(0); + to_radio_.setMaxLen(meshtastic_ToRadio_size); + to_radio_.setWriteCallback(onToRadioWrite, false); + to_radio_.begin(); + + from_radio_.setProperties(CHR_PROPS_READ); + from_radio_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); + from_radio_.setFixedLen(0); + from_radio_.setMaxLen(meshtastic_FromRadio_size); + from_radio_.setReadAuthorizeCallback(onFromRadioAuthorize, false); + from_radio_.begin(); { - service_.begin(); - bleLogBoth("[BLE][nrf52][mt] service begin"); - - to_radio_.setProperties(CHR_PROPS_WRITE); - to_radio_.setPermission(SECMODE_OPEN, SECMODE_OPEN); - to_radio_.setFixedLen(0); - to_radio_.setMaxLen(meshtastic_ToRadio_size); - to_radio_.setWriteCallback(onToRadioWrite, false); - to_radio_.begin(); - - from_radio_.setProperties(CHR_PROPS_READ); - from_radio_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); - from_radio_.setFixedLen(0); - from_radio_.setMaxLen(meshtastic_FromRadio_size); - from_radio_.setReadAuthorizeCallback(onFromRadioAuthorize, false); - from_radio_.begin(); - { - uint8_t empty = 0; - from_radio_.write(&empty, 0); - } - - from_num_.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ); - from_num_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); - from_num_.setFixedLen(4); - from_num_.write32(0); - from_num_.setCccdWriteCallback(onFromNumCccdWrite, false); - from_num_.begin(); - - log_radio_.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ); - log_radio_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); - log_radio_.setFixedLen(0); - log_radio_.setMaxLen(96); - log_radio_.begin(); - bleLogBoth("[BLE][nrf52][mt] chars ready"); - gatt_initialized_ = true; + uint8_t empty = 0; + from_radio_.write(&empty, 0); } - if (!observers_registered_) - { - ctx_.getChatService().addIncomingTextObserver(this); - ctx_.getChatService().addOutgoingTextObserver(this); - ctx_.getChatService().addIncomingDataObserver(this); - observers_registered_ = true; - } + from_num_.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ); + from_num_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); + from_num_.setFixedLen(4); + from_num_.write32(0); + from_num_.setCccdWriteCallback(onFromNumCccdWrite, false); + from_num_.begin(); + + log_radio_.setProperties(CHR_PROPS_NOTIFY | CHR_PROPS_READ); + log_radio_.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); + log_radio_.setFixedLen(0); + log_radio_.setMaxLen(96); + log_radio_.begin(); + bleLogBoth("[BLE][nrf52][mt] chars ready"); + + ctx_.getChatService().addIncomingTextObserver(this); + ctx_.getChatService().addOutgoingTextObserver(this); + ctx_.getChatService().addIncomingDataObserver(this); startAdvertising(service_); active_ = true; pending_passkey_.store(0); syncMqttProxySettings(); bleLogBoth("[BLE][nrf52][mt] service active"); + logFromRadioState("start_done", this); } void MeshtasticBleService::stop() { - if (observers_registered_) - { - ctx_.getChatService().removeIncomingTextObserver(this); - ctx_.getChatService().removeOutgoingTextObserver(this); - ctx_.getChatService().removeIncomingDataObserver(this); - observers_registered_ = false; - } + ctx_.getChatService().removeIncomingTextObserver(this); + ctx_.getChatService().removeOutgoingTextObserver(this); + ctx_.getChatService().removeIncomingDataObserver(this); disconnectAll(); Bluefruit.Advertising.stop(); @@ -662,10 +659,14 @@ void MeshtasticBleService::update() processPendingPairingRequest(); processPendingToRadio(); + if (from_radio_consume_pending_) { + logFromRadioState("update_before_consume", this); markReadableFromRadioConsumed(); + logFromRadioState("update_after_consume", this); } + handleToPhone(); prepareReadableFromRadio(); flushPendingFromNumNotify(); @@ -712,6 +713,12 @@ void MeshtasticBleService::onIncomingData(const chat::MeshIncomingData& msg) { if (phone_session_) { + bleLogBoth("[BLE][nrf52][mt] onIncomingData from=%08lX to=%08lX pkt=%08lX port=%u len=%u", + static_cast(msg.from), + static_cast(msg.to), + static_cast(msg.packet_id), + static_cast(msg.portnum), + static_cast(msg.payload.size())); phone_session_->onIncomingData(msg); if (phone_session_->isSendingPackets()) { @@ -761,8 +768,15 @@ void MeshtasticBleService::handleToPhone() return; } - Frame* frame = &pending_to_phone_; - if (!pending_to_phone_valid_) + Frame frame{}; + if (pending_to_phone_valid_) + { + frame = pending_to_phone_; + bleLogBoth("[BLE][nrf52][mt][flow] handleToPhone use-pending from_num=%08lX len=%u", + static_cast(frame.from_num), + static_cast(frame.len)); + } + else { if (!waiting_for_read && !can_prepare) { @@ -773,9 +787,8 @@ void MeshtasticBleService::handleToPhone() return; } - *frame = Frame{}; - session_frame_scratch_ = MeshtasticBleFrame{}; - if (!phone_session_->popToPhone(&session_frame_scratch_)) + MeshtasticBleFrame session_frame{}; + if (!phone_session_->popToPhone(&session_frame)) { if (waiting_for_read && in_send_packets) { @@ -784,12 +797,12 @@ void MeshtasticBleService::handleToPhone() return; } - if (session_frame_scratch_.len == 0 || session_frame_scratch_.len > frame->buf.size()) + if (session_frame.len == 0 || session_frame.len > frame.buf.size()) { bleLogBoth("[BLE][nrf52][mt] drop oversize to_phone frame from_num=%08lX len=%u max=%u", - static_cast(session_frame_scratch_.from_num), - static_cast(session_frame_scratch_.len), - static_cast(frame->buf.size())); + static_cast(session_frame.from_num), + static_cast(session_frame.len), + static_cast(frame.buf.size())); if (waiting_for_read && in_send_packets) { read_waiting_.store(false); @@ -797,21 +810,28 @@ void MeshtasticBleService::handleToPhone() return; } - frame->len = session_frame_scratch_.len; - frame->from_num = session_frame_scratch_.from_num; - std::memcpy(frame->buf.data(), session_frame_scratch_.buf, session_frame_scratch_.len); + bleLogBoth("[BLE][nrf52][mt][flow] handleToPhone pop from_num=%08lX len=%u buf=%p waiting=%u can_prepare=%u", + static_cast(session_frame.from_num), + static_cast(session_frame.len), + static_cast(session_frame.buf), + waiting_for_read ? 1U : 0U, + can_prepare ? 1U : 0U); + + frame.len = session_frame.len; + frame.from_num = session_frame.from_num; + std::memcpy(frame.buf.data(), session_frame.buf, session_frame.len); } - if (enqueueToPhoneFrame(*frame)) + if (enqueueToPhoneFrame(frame)) { pending_to_phone_valid_ = false; Serial2.printf("[BLE][nrf52][mt] to_phone enqueue from_num=%08lX len=%u q=%u\n", - static_cast(frame->from_num), - static_cast(frame->len), + static_cast(frame.from_num), + static_cast(frame.len), static_cast(to_phone_count_)); if (!waiting_for_read && (in_send_packets || config_flow_active)) { - notifyFromNum(frame->from_num); + notifyFromNum(frame.from_num); } else if (can_prepare && !config_flow_active && to_phone_count_ < kToPhoneQueueDepth) { @@ -820,11 +840,11 @@ void MeshtasticBleService::handleToPhone() } else { - pending_to_phone_ = *frame; + pending_to_phone_ = frame; pending_to_phone_valid_ = true; Serial2.printf("[BLE][nrf52][mt] to_phone defer from_num=%08lX len=%u\n", - static_cast(frame->from_num), - static_cast(frame->len)); + static_cast(frame.from_num), + static_cast(frame.len)); } } @@ -897,11 +917,25 @@ bool MeshtasticBleService::shouldBlockOnRead() const void MeshtasticBleService::beginReadWait() { + bleLogBoth("[BLE][nrf52][mt][flow] beginReadWait before read_waiting=%u preloaded_valid=%u consume_pending=%u from_num=%08lX len=%u", + isReadWaiting() ? 1U : 0U, + from_radio_preloaded_valid_ ? 1U : 0U, + from_radio_consume_pending_ ? 1U : 0U, + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.from_num : 0U), + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.len : 0U)); + read_waiting_.store(true); if (from_radio_preloaded_valid_) { from_radio_consume_pending_ = true; } + + bleLogBoth("[BLE][nrf52][mt][flow] beginReadWait after read_waiting=%u preloaded_valid=%u consume_pending=%u from_num=%08lX len=%u", + isReadWaiting() ? 1U : 0U, + from_radio_preloaded_valid_ ? 1U : 0U, + from_radio_consume_pending_ ? 1U : 0U, + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.from_num : 0U), + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.len : 0U)); } bool MeshtasticBleService::isReadWaiting() const @@ -993,6 +1027,11 @@ void MeshtasticBleService::prepareReadableFromRadio() { if (from_radio_preloaded_valid_) { + bleLogBoth("[BLE][nrf52][mt][flow] prepare skip preloaded_valid=1 consume_pending=%u read_waiting=%u from_num=%08lX len=%u", + from_radio_consume_pending_ ? 1U : 0U, + isReadWaiting() ? 1U : 0U, + static_cast(from_radio_preloaded_.from_num), + static_cast(from_radio_preloaded_.len)); return; } @@ -1002,9 +1041,18 @@ void MeshtasticBleService::prepareReadableFromRadio() return; } + bleLogBoth("[BLE][nrf52][mt][flow] prepare write from_num=%08lX len=%u buf=%p q=%u consume_pending=%u read_waiting=%u", + static_cast(frame.from_num), + static_cast(frame.len), + static_cast(frame.buf.data()), + static_cast(to_phone_count_), + from_radio_consume_pending_ ? 1U : 0U, + isReadWaiting() ? 1U : 0U); + from_radio_.write(frame.buf.data(), frame.len); from_radio_preloaded_ = frame; from_radio_preloaded_valid_ = true; + bleLogBoth("[BLE][nrf52][mt][flow] preload from_num=%08lX len=%u q=%u", static_cast(frame.from_num), static_cast(frame.len), @@ -1018,21 +1066,38 @@ bool MeshtasticBleService::hasReadableFromRadio() const void MeshtasticBleService::markReadableFromRadioConsumed() { + bleLogBoth("[BLE][nrf52][mt][flow] consume begin preloaded_valid=%u consume_pending=%u read_waiting=%u from_num=%08lX len=%u", + from_radio_preloaded_valid_ ? 1U : 0U, + from_radio_consume_pending_ ? 1U : 0U, + isReadWaiting() ? 1U : 0U, + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.from_num : 0U), + static_cast(from_radio_preloaded_valid_ ? from_radio_preloaded_.len : 0U)); + from_radio_consume_pending_ = false; if (!from_radio_preloaded_valid_) { pending_from_radio_empty_log_ = true; + bleLogBoth("[BLE][nrf52][mt][flow] consume empty"); return; } pending_from_radio_read_len_ = static_cast(from_radio_preloaded_.len); pending_from_radio_read_from_num_ = from_radio_preloaded_.from_num; pending_from_radio_read_log_ = true; + + bleLogBoth("[BLE][nrf52][mt][flow] consume frame from_num=%08lX len=%u buf=%p", + static_cast(from_radio_preloaded_.from_num), + static_cast(from_radio_preloaded_.len), + static_cast(from_radio_preloaded_.buf.data())); + from_radio_preloaded_valid_ = false; from_radio_preloaded_ = Frame{}; - uint8_t empty = 0; - from_radio_.write(&empty, 0); + + bleLogBoth("[BLE][nrf52][mt][flow] consume end preloaded_valid=%u consume_pending=%u read_waiting=%u", + from_radio_preloaded_valid_ ? 1U : 0U, + from_radio_consume_pending_ ? 1U : 0U, + isReadWaiting() ? 1U : 0U); } void MeshtasticBleService::handleConnectEvent(uint16_t conn_handle) @@ -1118,7 +1183,7 @@ bool MeshtasticBleService::getPairingStatus(BlePairingStatus* out) const } *out = BlePairingStatus{}; - out->available = active_; + out->available = ctx_.isBleEnabled(); out->requires_passkey = ble_config_.mode != meshtastic_Config_BluetoothConfig_PairingMode_NO_PIN; out->is_fixed_pin = ble_config_.mode == meshtastic_Config_BluetoothConfig_PairingMode_FIXED_PIN; out->is_connected = isBleConnected();