diff --git a/lib/tdeck_ui/UI/LXMF/UIManager.cpp b/lib/tdeck_ui/UI/LXMF/UIManager.cpp index c26791d1..7d96a942 100644 --- a/lib/tdeck_ui/UI/LXMF/UIManager.cpp +++ b/lib/tdeck_ui/UI/LXMF/UIManager.cpp @@ -981,6 +981,11 @@ bool UIManager::test_call_answer() { return true; } +std::string UIManager::test_lxst_dest_hex() const { + if (!_lxst_destination) return std::string(); + return _lxst_destination.hash().toHex(); +} + const char* UIManager::test_call_state_name() const { switch (_call_state) { case CallState::IDLE: return "IDLE"; @@ -1792,7 +1797,12 @@ void UIManager::call_answer() { void UIManager::announce_lxst() { if (_lxst_destination) { + std::string h = _lxst_destination.hash().toHex(); + INFO(("Announcing LXST telephony destination: " + h).c_str()); _lxst_destination.announce(); + INFO("LXST announce sent"); + } else { + WARNING("announce_lxst skipped: _lxst_destination not constructed"); } } diff --git a/lib/tdeck_ui/UI/LXMF/UIManager.h b/lib/tdeck_ui/UI/LXMF/UIManager.h index d31121dc..ece0b6fb 100644 --- a/lib/tdeck_ui/UI/LXMF/UIManager.h +++ b/lib/tdeck_ui/UI/LXMF/UIManager.h @@ -203,6 +203,10 @@ public: */ bool test_call_answer(); + /** Pyxis's lxst.telephony destination hash, hex. Empty if the + * LXST destination has not been registered yet (early boot). */ + std::string test_lxst_dest_hex() const; + /** * String name of the current call state, eg "IDLE", "ACTIVE", * "INCOMING_RINGING". Stable for harness assertions. diff --git a/src/main.cpp b/src/main.cpp index 4ae78d1c..3adb6fcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1655,6 +1655,17 @@ static void handle_test_hook_command(const String& line) { router->announce(); Serial.println("T:OK announced"); } + else if (cmd == "T:ANNLXST") { + // T:ANNLXST — force a fresh announce of the lxst.telephony + // destination. Required before pyxis-as-callee tests because + // the TCP-reconnect path at main.cpp:963 only announces LXMF; + // a brand-new boot ends up with the LXST destination absent + // from rnsd's cache, so the bot can resolve a path but the + // path doesn't actually route to pyxis. + if (!ui_manager) { Serial.println("T:ERR no ui_manager"); return; } + ui_manager->announce_lxst(); + Serial.println("T:OK announced"); + } else if (cmd == "T:PATHS") { const auto& path_table = RNS::Transport::get_path_table(); Serial.print("T:OK count="); @@ -1841,6 +1852,16 @@ static void handle_test_hook_command(const String& line) { } Serial.println("T:OK answered"); } + else if (cmd == "T:LXSTDEST") { + // T:LXSTDEST — pyxis's lxst.telephony destination hash. Used + // by the harness to set up pyxis-as-callee tests (the bot + // dials this hash). Returns "T:ERR not_ready" if the + // destination hasn't been registered yet (early boot). + if (!ui_manager) { Serial.println("T:ERR no ui_manager"); return; } + std::string h = ui_manager->test_lxst_dest_hex(); + if (h.empty()) { Serial.println("T:ERR not_ready"); return; } + Serial.println(String("T:OK ") + h.c_str()); + } else if (cmd == "T:CALL_STATS") { // T:CALL_STATS — return audio frame counters for the most recent // call. tx = frames sent over the wire (encoded by capture path),