mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-07-15 18:49:06 +00:00
ba18c32c04
Adds a USB-CDC serial command interface gated behind PYXIS_TEST_HOOKS
that lets a host-side harness drive pyxis end-to-end without UI taps.
Built specifically to run /tmp/tdeck_harness.py and prove LXMF DIRECT,
OPPORTUNISTIC, and PROPAGATED delivery against a Mac-side echo bot
over the Mac's rnsd + lxmd.
Commands (all newline-terminated, replies T:OK or T:ERR):
T:DEST — pyxis's delivery dest hash (hex)
T:ID — pyxis's identity hash (hex)
T:ANN — force an announce
T:PATHS — count + dump in-memory path table
T:HASPATH <hex> — Transport::has_path + in-memory check
T:RECALL <hex> — Identity::recall_app_data hex
T:SEND <hex> <text> — outbound DIRECT LXMessage
T:SENDOPP <hex> <text> — outbound OPPORTUNISTIC LXMessage
T:SENDPROP <hex> <text> — outbound PROPAGATED LXMessage
T:SETPROP <hex> <stamp_cost> — set outbound propagation node
T:SYNCPROP — request_messages_from_propagation_node
T:SYNCSTATE — current PR_* sync state
T:STATE <msg_hash> — LXMessage state for a tracked send
T:RX — drain inbound RX ring
T:RXCLR — clear RX ring
Build-flag side:
-DPYXIS_TEST_HOOKS — gates all of the above
-DPYXIS_TEST_TCP_HOST="..." — hard-overrides NVS tcp_host so the
harness's rnsd is the only target
-DPYXIS_TEST_TCP_PORT=... — same for tcp_port
Also: replaces `lib_extra_dirs = deps/microReticulum` with an explicit
`file://~/repos/microReticulum` lib_dep. lib_extra_dirs
caused PIO to compile microReticulum twice (once through the extra
dir, once through microLXMF's transitive auto-fetch), producing two
copies of `Transport::_path_store` in BSS. Different translation
units linked against different statics, so put() and exists() landed
in different in-memory indexes. Symptom: `T:HASPATH` returned 0 even
when the previous announce's `[ustore] put: wrote key` log line was
visible. Single source path → single static → consistent reads.
`patch_filestore.py` is committed but commented out in extra_scripts
— used during diagnostic when the dual-static issue was being
triaged. Easy to re-arm if FileStore put/exists drift recurs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.8 KiB
Python
71 lines
2.8 KiB
Python
"""
|
|
PlatformIO pre-build script: TEMPORARY diagnostic patch for
|
|
microStore's FileStore::exists().
|
|
|
|
Adds a printf at the top of `bool exists(const uint8_t*, uint8_t)` so
|
|
we can see why the path-table store's exists returns false even when
|
|
the most recent put for the same key succeeded. Remove once the
|
|
investigation is done.
|
|
"""
|
|
Import("env")
|
|
import os
|
|
|
|
FILESTORE_H = os.path.join(
|
|
env.get("PROJECT_DIR", "."),
|
|
".pio", "libdeps", "tdeck", "microStore", "include", "microStore", "FileStore.h",
|
|
)
|
|
|
|
OLD = """\tbool exists(const uint8_t* key, uint8_t key_len)
|
|
\t{
|
|
if (!isValid()) return false;
|
|
\t\tif(key_len > USTORE_MAX_KEY_LEN) return false;
|
|
\t\tIndexValue* e = index_find(key, key_len);
|
|
\t\tif (!e) return false;
|
|
\t\tif (is_ttl_expired_(e->timestamp, e->ttl)) { index_remove(key, key_len); return false; }
|
|
\t\treturn true;
|
|
\t}"""
|
|
|
|
NEW = """\tbool exists(const uint8_t* key, uint8_t key_len)
|
|
\t{
|
|
\t\tif (!isValid()) { printf("[ustore] exists: !isValid len=%u idx_size=%zu store=%p\\n", (unsigned)key_len, _index.size(), (void*)this); return false; }
|
|
\t\tif(key_len > USTORE_MAX_KEY_LEN) { printf("[ustore] exists: key too long\\n"); return false; }
|
|
\t\tIndexValue* e = index_find(key, key_len);
|
|
\t\tif (!e) { printf("[ustore] exists: not_in_index len=%u key=%s idx_size=%zu store=%p\\n", (unsigned)key_len, bin_str(key, key_len), _index.size(), (void*)this); return false; }
|
|
\t\tif (is_ttl_expired_(e->timestamp, e->ttl)) { printf("[ustore] exists: ttl_expired ts=%u ttl=%u now=%u\\n", e->timestamp, e->ttl, microStore::time()); index_remove(key, key_len); return false; }
|
|
\t\tprintf("[ustore] exists: found key=%s store=%p\\n", bin_str(key, key_len), (void*)this);
|
|
\t\treturn true;
|
|
\t}"""
|
|
|
|
PUT_OLD = """\t\tindex_insert(key, key_len, current_segment, offset, ts, ttl);
|
|
|
|
\t\t// Enforce max_recs:"""
|
|
|
|
PUT_NEW = """\t\tindex_insert(key, key_len, current_segment, offset, ts, ttl);
|
|
\t\tprintf("[ustore] put: index_insert done key=%s idx_size=%zu store=%p\\n", bin_str(key, key_len), _index.size(), (void*)this);
|
|
|
|
\t\t// Enforce max_recs:"""
|
|
|
|
def patch(content):
|
|
out = content
|
|
if OLD in out:
|
|
out = out.replace(OLD, NEW)
|
|
print("PATCH: FileStore.h: exists() diagnostics added")
|
|
elif "store=%p" in content and "exists:" in content:
|
|
print("PATCH: FileStore.h: exists() already patched")
|
|
if PUT_OLD in out:
|
|
out = out.replace(PUT_OLD, PUT_NEW)
|
|
print("PATCH: FileStore.h: put-after-insert diagnostics added")
|
|
elif "put: index_insert done" in content:
|
|
print("PATCH: FileStore.h: put-after-insert already patched")
|
|
return out
|
|
|
|
if os.path.exists(FILESTORE_H):
|
|
with open(FILESTORE_H) as f:
|
|
content = f.read()
|
|
new = patch(content)
|
|
if new != content:
|
|
with open(FILESTORE_H, "w") as f:
|
|
f.write(new)
|
|
else:
|
|
print("PATCH: FileStore.h not found, skipping")
|