mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
Merge branch 'feat/save-app-room-password'
Persist app/USB-entered room passwords on device (rooms post standalone after reboot), plus Messages-screen docs for on-device room login.
This commit is contained in:
@@ -40,6 +40,19 @@ Sensor placeholders appear automatically in the placeholder picker when the corr
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Rooms — logging in
|
||||||
|
|
||||||
|
Posting to a **room server** requires a login handshake first, so the device can log in on its own — no phone app needed. The first time you press **Enter** on a room, a password prompt opens automatically; type the room's password and press the **✓** key (leave it empty and submit for open / no-password rooms).
|
||||||
|
|
||||||
|
- **Passwords are remembered across reboots.** After a successful login the password is saved on the device, so picking that room again — even after a power cycle — logs back in silently without re-prompting.
|
||||||
|
- **A wrong or changed password self-heals.** If a saved password stops working (e.g. the server's password was changed), the failed login forgets it, so the next **Enter** prompts you to type a new one.
|
||||||
|
- **Re-login any time** with **Hold Enter** on the room → **Login…** (see the room context menu below) — useful to switch to a new password without waiting for a failure.
|
||||||
|
- Passwords set from the **phone app** are saved on the device too, so it can post to that room standalone after a reboot.
|
||||||
|
|
||||||
|
> The on-screen keyboard is limited to ASCII (letters, digits and common symbols); accented characters such as `ą`/`ę` can't be typed on the device. A password containing them can still be set from the phone app — the device stores and replays it byte-for-byte.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Message history
|
### Message history
|
||||||
|
|
||||||
| OLED | E-Ink |
|
| OLED | E-Ink |
|
||||||
@@ -92,6 +105,12 @@ A location is any `lat,lon` pair in the text — exactly what the `{loc}` placeh
|
|||||||
|
|
||||||
When **Pin to dial** is selected, a slot picker opens (Slot 1–6 showing current occupant name or "empty"). Choosing a slot that already holds another contact moves the new contact there.
|
When **Pin to dial** is selected, a slot picker opens (Slot 1–6 showing current occupant name or "empty"). Choosing a slot that already holds another contact moves the new contact there.
|
||||||
|
|
||||||
|
In the **Rooms** list the context menu instead offers a single item:
|
||||||
|
|
||||||
|
| Item | Action |
|
||||||
|
| ------- | ---------------------------------------------------------------------------- |
|
||||||
|
| Login… | Opens the password prompt to (re-)log in to this room (see Rooms — logging in) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Context menu — channel list
|
### Context menu — channel list
|
||||||
|
|||||||
@@ -845,11 +845,13 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
|
|||||||
pending_login = 0;
|
pending_login = 0;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
bool login_ok = false;
|
||||||
if (memcmp(&data[4], "OK", 2) == 0) { // legacy Repeater login OK response
|
if (memcmp(&data[4], "OK", 2) == 0) { // legacy Repeater login OK response
|
||||||
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
|
out_frame[i++] = PUSH_CODE_LOGIN_SUCCESS;
|
||||||
out_frame[i++] = 0; // legacy: is_admin = false
|
out_frame[i++] = 0; // legacy: is_admin = false
|
||||||
memcpy(&out_frame[i], contact.id.pub_key, 6);
|
memcpy(&out_frame[i], contact.id.pub_key, 6);
|
||||||
i += 6; // pub_key_prefix
|
i += 6; // pub_key_prefix
|
||||||
|
login_ok = true;
|
||||||
} else if (data[4] == RESP_SERVER_LOGIN_OK) { // new login response
|
} else if (data[4] == RESP_SERVER_LOGIN_OK) { // new login response
|
||||||
uint16_t keep_alive_secs = ((uint16_t)data[5]) * 16;
|
uint16_t keep_alive_secs = ((uint16_t)data[5]) * 16;
|
||||||
if (keep_alive_secs > 0) {
|
if (keep_alive_secs > 0) {
|
||||||
@@ -863,12 +865,21 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
|
|||||||
i += 4; // NEW: include server timestamp
|
i += 4; // NEW: include server timestamp
|
||||||
out_frame[i++] = data[7]; // NEW (v7): ACL permissions
|
out_frame[i++] = data[7]; // NEW (v7): ACL permissions
|
||||||
out_frame[i++] = data[12]; // FIRMWARE_VER_LEVEL
|
out_frame[i++] = data[12]; // FIRMWARE_VER_LEVEL
|
||||||
|
login_ok = true;
|
||||||
} else {
|
} else {
|
||||||
out_frame[i++] = PUSH_CODE_LOGIN_FAIL;
|
out_frame[i++] = PUSH_CODE_LOGIN_FAIL;
|
||||||
out_frame[i++] = 0; // reserved
|
out_frame[i++] = 0; // reserved
|
||||||
memcpy(&out_frame[i], contact.id.pub_key, 6);
|
memcpy(&out_frame[i], contact.id.pub_key, 6);
|
||||||
i += 6; // pub_key_prefix
|
i += 6; // pub_key_prefix
|
||||||
}
|
}
|
||||||
|
// Persist app/USB-entered room passwords too, so the device can later post
|
||||||
|
// to that room standalone (after reboot, no phone) without re-prompting --
|
||||||
|
// same store the on-device login path uses. Rooms only; a failed login
|
||||||
|
// forgets any stale saved password, mirroring onRoomLoginResult().
|
||||||
|
if (contact.type == ADV_TYPE_ROOM) {
|
||||||
|
if (login_ok) saveRoomPassword(contact.id.pub_key, pending_login_pw);
|
||||||
|
else forgetRoomPassword(contact.id.pub_key);
|
||||||
|
}
|
||||||
_serial->writeFrame(out_frame, i);
|
_serial->writeFrame(out_frame, i);
|
||||||
} else if (ui_pending_login && memcmp(&ui_pending_login, contact.id.pub_key, 4) == 0) { // check for on-device UI login response
|
} else if (ui_pending_login && memcmp(&ui_pending_login, contact.id.pub_key, 4) == 0) { // check for on-device UI login response
|
||||||
ui_pending_login = 0;
|
ui_pending_login = 0;
|
||||||
@@ -2185,6 +2196,8 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
} else {
|
} else {
|
||||||
clearPendingReqs();
|
clearPendingReqs();
|
||||||
memcpy(&pending_login, recipient->id.pub_key, 4); // match this to onContactResponse()
|
memcpy(&pending_login, recipient->id.pub_key, 4); // match this to onContactResponse()
|
||||||
|
strncpy(pending_login_pw, password, sizeof(pending_login_pw) - 1); // saved on success if it's a room
|
||||||
|
pending_login_pw[sizeof(pending_login_pw) - 1] = 0;
|
||||||
out_frame[0] = RESP_CODE_SENT;
|
out_frame[0] = RESP_CODE_SENT;
|
||||||
out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0;
|
out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0;
|
||||||
memcpy(&out_frame[2], &pending_login, 4);
|
memcpy(&out_frame[2], &pending_login, 4);
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ private:
|
|||||||
NodePrefs _prefs;
|
NodePrefs _prefs;
|
||||||
uint32_t pending_login;
|
uint32_t pending_login;
|
||||||
uint32_t ui_pending_login; // like pending_login, but triggered by on-device UI instead of BLE/USB app
|
uint32_t ui_pending_login; // like pending_login, but triggered by on-device UI instead of BLE/USB app
|
||||||
|
char pending_login_pw[16]; // password of the in-flight app/USB login, persisted on success for ADV_TYPE_ROOM (see saveRoomPassword)
|
||||||
uint32_t pending_status;
|
uint32_t pending_status;
|
||||||
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
|
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
|
||||||
uint32_t pending_req; // pending _BINARY_REQ
|
uint32_t pending_req; // pending _BINARY_REQ
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
- **Trail auto-pause** — recording **freezes on stops** (banking elapsed time and breaking the map line across the idle gap) and **resumes on movement** without ending the session; the home-screen blink keeps going while paused.
|
- **Trail auto-pause** — recording **freezes on stops** (banking elapsed time and breaking the map line across the idle gap) and **resumes on movement** without ending the session; the home-screen blink keeps going while paused.
|
||||||
- **Collapsible Tools** — tools are grouped into fold-in-place **Location / Comms / System** sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses **page-indicator icons** instead of dots.
|
- **Collapsible Tools** — tools are grouped into fold-in-place **Location / Comms / System** sections, the same model as Settings (Tools always opens folded to the section list), and the home carousel now uses **page-indicator icons** instead of dots.
|
||||||
- **Waypoint coordinate editor** — add a waypoint by scroll-editing its latitude/longitude digit by digit.
|
- **Waypoint coordinate editor** — add a waypoint by scroll-editing its latitude/longitude digit by digit.
|
||||||
- **On-device room login with saved passwords** — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's **context-menu "Login…"**. The password is **remembered across reboots**, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.
|
- **On-device room login with saved passwords** — log in to a room server straight from the device (no phone app): pick the room and the password prompt appears automatically (a blank password works for open rooms), or re-login any time via the room's **context-menu "Login…"**. The password is **remembered across reboots**, so a room you've used before logs back in without retyping; a failed login (e.g. the server's password changed) forgets the stale password so the next attempt prompts again. Room passwords entered via the **phone app** are saved on the device too, so it can post to that room standalone after a reboot. Saved passwords are written with the same atomic, crash-safe persistence as contacts and channels.
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user