repeater admin login regression bugfix and timing response improvements

This commit is contained in:
pelgraine
2026-03-05 18:04:28 +11:00
parent db58f8cf87
commit e91ad4bac4
3 changed files with 37 additions and 21 deletions

View File

@@ -694,17 +694,25 @@ bool MyMesh::uiSendDirectMessage(uint32_t contact_idx, const char* text) {
return true;
}
bool MyMesh::uiLoginToRepeater(uint32_t contact_idx, const char* password) {
bool MyMesh::uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms) {
ContactInfo contact;
if (!getContactByIdx(contact_idx, contact)) return false;
ContactInfo* recipient = lookupContactByPubKey(contact.id.pub_key, PUB_KEY_SIZE);
if (!recipient) return false;
uint32_t est_timeout;
int result = sendLogin(*recipient, password, est_timeout);
// Force flood routing for login — a mobile repeater's direct path may be stale.
// The companion protocol does the same for telemetry requests.
int8_t save_path_len = recipient->out_path_len;
recipient->out_path_len = -1;
int result = sendLogin(*recipient, password, est_timeout_ms);
recipient->out_path_len = save_path_len; // restore
if (result == MSG_SEND_FAILED) {
MESH_DEBUG_PRINTLN("UI: Admin login send failed to %s", recipient->name);
est_timeout_ms = 0;
return false;
}
@@ -712,9 +720,8 @@ bool MyMesh::uiLoginToRepeater(uint32_t contact_idx, const char* password) {
memcpy(&pending_login, recipient->id.pub_key, 4);
_admin_contact_idx = contact_idx;
MESH_DEBUG_PRINTLN("UI: Admin login sent to %s (%s), timeout=%dms",
recipient->name, result == MSG_SEND_SENT_FLOOD ? "flood" : "direct",
est_timeout);
MESH_DEBUG_PRINTLN("UI: Admin login sent to %s (flood, was path_len=%d), timeout=%dms",
recipient->name, (int)save_path_len, est_timeout_ms);
return true;
}

View File

@@ -127,7 +127,7 @@ public:
bool uiSendDirectMessage(uint32_t contact_idx, const char* text);
// Repeater admin - UI-initiated operations
bool uiLoginToRepeater(uint32_t contact_idx, const char* password);
bool uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms);
bool uiSendCliCommand(uint32_t contact_idx, const char* command);
bool uiSendTelemetryRequest(uint32_t contact_idx);
int getAdminContactIdx() const { return _admin_contact_idx; }

View File

@@ -197,6 +197,7 @@ private:
// Timing
unsigned long _cmdSentAt;
unsigned long _loginTimeoutMs; // computed timeout for login (ms), falls back to ADMIN_TIMEOUT_MS
bool _waitingForLogin;
// Password cache
@@ -428,7 +429,7 @@ public:
_catSel(0), _cmdSel(0), _scrollOffset(0),
_paramLen(0), _pendingCmd(nullptr),
_responseLen(0), _responseScroll(0), _responseTotalLines(0),
_cmdSentAt(0), _waitingForLogin(false), _pwdCacheCount(0),
_cmdSentAt(0), _loginTimeoutMs(ADMIN_TIMEOUT_MS), _waitingForLogin(false), _pwdCacheCount(0),
_telemVoltage(0), _telemTempC(0),
_telemHasVoltage(false), _telemHasTemp(false), _telemRequested(false) {
_password[0] = '\0';
@@ -529,19 +530,23 @@ public:
}
void poll() override {
if ((_state == STATE_LOGGING_IN || _state == STATE_COMMAND_PENDING) &&
_cmdSentAt > 0 && (millis() - _cmdSentAt) > ADMIN_TIMEOUT_MS) {
if (_pendingCmd && (_pendingCmd->flags & CMDF_EXPECT_TIMEOUT)) {
snprintf(_response, sizeof(_response), "Command sent.\nTimeout is expected\n(device is rebooting/updating).");
_responseLen = strlen(_response);
_responseTotalLines = countLines(_response);
_state = STATE_RESPONSE_VIEW;
} else {
snprintf(_response, sizeof(_response), "Timeout - no response.");
_responseLen = strlen(_response);
_state = STATE_ERROR;
if (_cmdSentAt > 0) {
unsigned long elapsed = millis() - _cmdSentAt;
unsigned long timeout = (_state == STATE_LOGGING_IN) ? _loginTimeoutMs : ADMIN_TIMEOUT_MS;
if ((_state == STATE_LOGGING_IN || _state == STATE_COMMAND_PENDING) && elapsed > timeout) {
if (_pendingCmd && (_pendingCmd->flags & CMDF_EXPECT_TIMEOUT)) {
snprintf(_response, sizeof(_response), "Command sent.\nTimeout is expected\n(device is rebooting/updating).");
_responseLen = strlen(_response);
_responseTotalLines = countLines(_response);
_state = STATE_RESPONSE_VIEW;
} else {
snprintf(_response, sizeof(_response), "Timeout - no response.");
_responseLen = strlen(_response);
_state = STATE_ERROR;
}
_task->forceRefresh(); // Immediate redraw on state change
}
_task->forceRefresh(); // Immediate redraw on state change
}
}
@@ -1160,9 +1165,13 @@ private:
inline bool RepeaterAdminScreen::doLogin() {
if (_contactIdx < 0 || _pwdLen == 0) return false;
if (the_mesh.uiLoginToRepeater(_contactIdx, _password)) {
uint32_t timeout_ms = 0;
if (the_mesh.uiLoginToRepeater(_contactIdx, _password, timeout_ms)) {
_state = STATE_LOGGING_IN;
_cmdSentAt = millis();
// Add a 1.5s buffer over the mesh estimate; fall back to ADMIN_TIMEOUT_MS
// if the estimate came back zero for any reason.
_loginTimeoutMs = (timeout_ms > 0) ? timeout_ms + 1500 : ADMIN_TIMEOUT_MS;
_waitingForLogin = true;
return true;
} else {