mirror of
https://github.com/pelgraine/Meck.git
synced 2026-08-08 17:52:44 +02:00
T-Watch: fix path editor screen setting for repeater admin via custom paths.
Fix haptic power for watch s3
This commit is contained in:
@@ -1307,8 +1307,20 @@ bool MyMesh::onContactPathRecv(ContactInfo& contact, uint8_t* in_path, uint8_t i
|
||||
// auto-discovery overwrite it. Skip the base class call entirely — ACKs
|
||||
// embedded in path responses will still be delivered via separate ACK packets.
|
||||
if (contact.flags & CONTACT_FLAG_CUSTOM_PATH) {
|
||||
#if defined(MECK_TWATCH)
|
||||
// Watch: keep the manually set path (don't let discovery overwrite it), but
|
||||
// STILL deliver an embedded login/response reply riding on this path packet
|
||||
// -- otherwise logins to custom-path contacts silently time out. Gated to
|
||||
// the watch so other builds' admin flow is unchanged.
|
||||
MESH_DEBUG_PRINTLN("onContactPathRecv: custom-path %s, keeping path, delivering response (type=%d len=%d)", contact.name, extra_type, extra_len);
|
||||
if (extra_type == PAYLOAD_TYPE_RESPONSE && extra_len > 0) {
|
||||
onContactResponse(contact, extra, extra_len);
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
MESH_DEBUG_PRINTLN("onContactPathRecv: skipping path update for custom-path contact %s", contact.name);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
return BaseChatMesh::onContactPathRecv(contact, in_path, in_path_len, out_path, out_path_len, extra_type, extra, extra_len);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ private:
|
||||
|
||||
bool _dirty; // Path has been modified
|
||||
bool _wantExit; // Set by Save & Exit — caller should navigate back
|
||||
#if defined(MECK_TWATCH)
|
||||
bool _wantKeyboard = false; // Set by Add hop -- caller opens the path keyboard
|
||||
#endif
|
||||
bool _directLocked; // True = path is explicitly set to direct (0 hops, locked)
|
||||
|
||||
// --- helpers ---
|
||||
@@ -189,6 +192,9 @@ public:
|
||||
_repScroll = 0;
|
||||
_dirty = false;
|
||||
_wantExit = false;
|
||||
#if defined(MECK_TWATCH)
|
||||
_wantKeyboard = false;
|
||||
#endif
|
||||
_directLocked = false;
|
||||
|
||||
// Load contact info
|
||||
@@ -489,6 +495,61 @@ public:
|
||||
return 5000;
|
||||
}
|
||||
|
||||
#if defined(MECK_TWATCH)
|
||||
// Watch: replace the whole path from a typed string of comma-separated hex
|
||||
// hops. Each hop is _bytesPerHop bytes (2*_bytesPerHop hex chars), matching
|
||||
// the current mode toggle -- e.g. 1B "36,21,dd", 2B "3601,2198,dddd", 3B
|
||||
// "360184,2198a7,dddddd". Returns NULL on success, or an error message (the
|
||||
// existing path is left unchanged on any error). UITask is only forward
|
||||
// declared here, so the caller shows the alert rather than this method.
|
||||
const char* applyComposedPath(const char* str) {
|
||||
if (str == nullptr) return "Empty path";
|
||||
const int expectChars = _bytesPerHop * 2;
|
||||
uint8_t tmp[MAX_PATH_SIZE];
|
||||
int nbytes = 0, hops = 0;
|
||||
const char* p = str;
|
||||
while (*p) {
|
||||
char tok[16];
|
||||
int tlen = 0;
|
||||
while (*p && *p != ',') {
|
||||
if (*p != ' ') {
|
||||
if (tlen >= (int)sizeof(tok) - 1) return "Hop too long";
|
||||
tok[tlen++] = *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (*p == ',') p++;
|
||||
if (tlen == 0) continue; // tolerate stray/trailing commas
|
||||
if (tlen != expectChars) return "Wrong hop length";
|
||||
if (hops >= 8) return "Max 8 hops";
|
||||
for (int b = 0; b < _bytesPerHop; b++) {
|
||||
int hi = hexNibble(tok[b * 2]);
|
||||
int lo = hexNibble(tok[b * 2 + 1]);
|
||||
if (hi < 0 || lo < 0) return "Bad hex";
|
||||
if (nbytes >= MAX_PATH_SIZE) return "Path too long";
|
||||
tmp[nbytes++] = (uint8_t)((hi << 4) | lo);
|
||||
}
|
||||
hops++;
|
||||
}
|
||||
if (hops == 0) return "Empty path";
|
||||
memset(_pathBuf, 0, sizeof(_pathBuf));
|
||||
memcpy(_pathBuf, tmp, nbytes);
|
||||
_hopCount = hops;
|
||||
_pathLen = encodePath();
|
||||
_directLocked = false;
|
||||
_dirty = true;
|
||||
_menuCount = buildMenuCount();
|
||||
_menuSel = 0;
|
||||
return nullptr;
|
||||
}
|
||||
static int hexNibble(char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool handleInput(char c) override {
|
||||
if (_state == STATE_PICK_HOP) {
|
||||
return handlePickerInput(c);
|
||||
@@ -551,12 +612,19 @@ public:
|
||||
return true;
|
||||
|
||||
case MENU_ADD_HOP:
|
||||
// Enter picker mode — adding a hop clears direct lock
|
||||
_directLocked = false;
|
||||
#if defined(MECK_TWATCH)
|
||||
// Watch: request the on-screen keyboard to type the whole path as
|
||||
// comma-separated hex hops. main loop polls wantsKeyboard() and opens
|
||||
// it (UITask is only forward declared here, so we can't call it).
|
||||
_wantKeyboard = true;
|
||||
#else
|
||||
// Enter picker mode -- adding a hop clears direct lock
|
||||
buildRepeaterList();
|
||||
_repSel = 0;
|
||||
_repScroll = 0;
|
||||
_state = STATE_PICK_HOP;
|
||||
#endif
|
||||
return true;
|
||||
|
||||
case MENU_SET_DIRECT:
|
||||
@@ -706,6 +774,11 @@ public:
|
||||
EditorState getState() const { return _state; }
|
||||
bool isDirty() const { return _dirty; }
|
||||
bool wantsExit() const { return _wantExit; }
|
||||
#if defined(MECK_TWATCH)
|
||||
bool wantsKeyboard() const { return _wantKeyboard; }
|
||||
void clearWantKeyboard() { _wantKeyboard = false; }
|
||||
int getContactIdx() const { return _contactIdx; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
void switchMode(int newBytesPerHop) {
|
||||
|
||||
@@ -2592,6 +2592,13 @@ if (curr) curr->poll();
|
||||
gotoHomeScreen();
|
||||
}
|
||||
showAlert(dmSuccess ? "DM sent!" : "DM failed!", 1500);
|
||||
} else if (purpose == TWatchKeyboardScreen::TWKB_PATH) {
|
||||
PathEditorScreen* pe = (PathEditorScreen*)getPathEditorScreen();
|
||||
const char* perr = pe ? pe->applyComposedPath(sendText) : "No editor";
|
||||
kb->clearOutBuf();
|
||||
if (path_editor) setCurrScreen(path_editor);
|
||||
else gotoHomeScreen();
|
||||
if (perr) showAlert(perr, 1500);
|
||||
} else { // TWKB_ADMIN_PASSWORD or TWKB_ADMIN_CLI
|
||||
RepeaterAdminScreen* admin = (RepeaterAdminScreen*)getRepeaterAdminScreen();
|
||||
if (admin) {
|
||||
@@ -2604,6 +2611,13 @@ if (curr) curr->poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (curr == path_editor && path_editor != nullptr) {
|
||||
PathEditorScreen* pe = (PathEditorScreen*)path_editor;
|
||||
if (pe->wantsKeyboard()) {
|
||||
pe->clearWantKeyboard();
|
||||
openTWatchKeyboard(TWatchKeyboardScreen::TWKB_PATH, pe->getContactIdx());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_display != NULL && _display->isOn()) {
|
||||
|
||||
Reference in New Issue
Block a user