Commit graph

174 commits

Author SHA1 Message Date
torlando-tech
0afd5019b1 fix: BLE shutdown cleanup + battery-tunable power settings
Fix timing bug where BLE scanner/advertiser/GATT connections persist after
service restart because System.exit(0) kills the process before the async
Python shutdown chain can complete. Add synchronous stopImmediate() methods
that run directly on Main thread before process exit.

Add user-configurable BLE power settings (Performance/Balanced/Battery Saver/
Custom presets) with per-interface controls for scan interval, scan duration,
and advertising refresh interval. Settings flow through the full stack:
UI → Room DB → Python config → Kotlin BLE bridge → Scanner/Advertiser.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:09:44 -05:00
matthieu Texier
8d57749343 perf: use O(1) set membership for telemetry allowlist check
telemetry_allowed_requesters is already a set of lowercase strings;
remove redundant list comprehension that converted to O(n) scan.
2026-03-03 17:12:07 +01:00
matthieu Texier
da84a61351 Fix telemetry host allowlist canonicalization and map self-echo marker filtering 2026-03-03 14:09:39 +01:00
Torlando
4988751a44
Merge pull request #584 from torlando-tech/fix/sentry-triage-anr-oom-duplicates
fix: resolve 4 Sentry issues — ANRs, OOM, duplicate keys
2026-03-02 18:31:53 -05:00
torlando-tech
ced6fdd597 fix: hot-add network interfaces to AutoInterface on connectivity change
When Columba starts without WiFi (or with only cellular), AutoInterface
scans for network interfaces once during __init__ and never again. If
WiFi connects later, the new wlan0 interface is invisible — no multicast
discovery sockets are created, no peers are found.

Two bugs fixed:

1. NetworkChangeManager only fired on network *switches* (lastNetworkId
   != null), not on first connection. Changed condition to also fire
   when lastNetworkId is null, with the existing binder.isInitialized()
   guard preventing premature invocation during startup.

2. No mechanism existed to tell AutoInterface about new interfaces.
   Added auto_interface_manager.py which surgically hot-adds only NEW
   interfaces to the existing AutoInterface — creating multicast/unicast
   discovery sockets, joining the multicast group, starting discovery
   threads, and creating UDP data servers. This avoids tearing down
   existing peer connections on already-adopted interfaces.

The hot-add runs before the LXMF announce on network change, so the
announce goes out on the newly added interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:42:09 -05:00
torlando-tech
b363654af8 fix: resolve 4 Sentry issues — ANRs, OOM, duplicate keys
COLUMBA-16: Wrap probeLinkSpeed() IPC in withContext(Dispatchers.IO)
to prevent ANR when called from Main thread via MessagingScreen.

COLUMBA-4Q: Convert restoreAnnounceIdentities() to suspend fun and
wrap IPC call in withContext(Dispatchers.IO) to prevent ANR during
interface restart identity restoration.

COLUMBA-4R: Prevent OOM from 222MB+ JSON parse of large attachments.
Python now writes attachments >2MB to staging files instead of
hex-encoding inline. Kotlin adds 10MB size guard before JSONObject
parse and resolves staging files via _binary_ref for direct binary
loading without hex encode/decode overhead.

COLUMBA-3F: Add SELECT DISTINCT to getEnrichedContacts query to
prevent duplicate rows from multi-announce LEFT JOINs, which caused
"Key was already used" crashes in LazyColumn. Defense-in-depth
distinctBy added in ContactsViewModel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:30:18 -05:00
matthieu Texier
43d1db8918 fix: include host device location in hosted group telemetry stream
Add 'Myself' as selectable group host and implement host self-telemetry storage so a hosting device includes its own coordinates in group telemetry behavior.

Unify local/remote collector send flow via TelemetryCollectorManager, store local telemetry through storeOwnTelemetry when collector=self, and re-sync Python host mode before local store to prevent intermittent 'Host mode not enabled'.

Also update UI/Settings behavior so host selection and host mode activation are explicit separate controls, and add/adjust tests across Kotlin and Python paths.
2026-02-26 16:13:01 +01:00
torlando-tech
14425c4fff fix: prevent delivered message status from regressing to sent/propagated
LXMF fires spurious failure/sent callbacks after a message is already
confirmed delivered. This triggered propagation retries that overwrote
'delivered' (double checkmark) with 'propagated' (single checkmark).

Python: add _successfully_delivered tracking set (mirrors existing
_successfully_propagated pattern) to guard _on_message_delivered,
_on_message_failed, and _on_message_sent from regressing state.

Kotlin: make 'delivered' truly terminal — block any status update that
would change it to a non-delivered state (defense-in-depth).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:55:05 -05:00
Torlando
450e8da030
Merge pull request #519 from torlando-tech/fix/announce-interface-lookup-main
fix: announce interface identification when transport disabled
2026-02-21 20:28:34 -05:00
torlando-tech
9b0d0715ca fix: resolve announce interface identification when transport is disabled
The announce_table in RNS is only populated when transport mode is enabled.
On non-transport nodes, interface extraction always returned None, causing
announces to show "Unknown" interface.

Extract interface lookup into python/interface_lookup.py module that checks
announce_table first, then falls back to path_table (which is always
populated regardless of transport mode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:31:10 -05:00
Torlando
7748d060fc
Merge pull request #504 from torlando-tech/perf/reduce-battery-drain
perf: reduce battery drain by 88% fewer timer wake-ups
2026-02-21 17:08:52 -05:00
torlando-tech
aee0a642a5 style: use FIELD_FILE_ATTACHMENTS constant instead of magic number
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:41:21 -05:00
torlando-tech
255c148fec fix: send pending file notification eagerly on propagation fallback
When a large file attachment exceeds the recipient's size limit and
falls back to propagation, notify the recipient immediately rather
than waiting for propagation to succeed. The previous deferred
approach had three bugs that prevented the notification from ever
appearing:

1. Tracking entry was placed after the immediate-success return,
   so synchronous propagation success skipped notification entirely
2. If propagation failed (max_relay_retries_exceeded), the
   notification was never sent since it waited for success
3. Field 16 (APP_EXTENSIONS_FIELD) was not in the meaningful_fields
   set, so the recipient's _on_lxmf_delivery filtered the
   notification as an "empty probe message"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:27:29 -05:00
torlando-tech
79b53cbbf7 cleanup: fix stale comments/logs from heartbeat interval change
Update 4 Python docstrings and 1 log message that still referenced
the old 1s heartbeat interval after it was changed to 5s idle.
Remove dead WifiLock entries from detekt NoRelaxedMocksRule allowlist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:19:18 -05:00
torlando-tech
6b3e697ec3 perf: reduce battery drain by 88% fewer timer wake-ups
Remove WiFi lock (WIFI_MODE_FULL_HIGH_PERF) — the battery whitelist already
ensures network access during Doze, and 802.11 power-save mode only adds
100-300ms latency without dropping the TCP connection. Briar operates
successfully without a WiFi lock. This alone reduces WiFi radio power by ~10x
during idle periods.

Increase health check interval from 5s to 30s (stale threshold 10s→60s),
lock refresh interval from 5min to 2h, Python maintenance loop from 1s to
30s, and Python heartbeat idle interval from 1s to 5s. These were all
over-provisioned relative to their actual detection/timeout requirements.

Net effect: timer-driven wake-ups drop from ~7,932/hour to ~960/hour.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 12:04:06 -05:00
torlando-tech
749124d2b2 Raise on TorClientInterface deployment failure instead of warning
When both deployment methods fail (filesystem copy and pkgutil),
raise FileNotFoundError so the caller's try/except and has_socks
check can properly fail-fast.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:53:40 -05:00
torlando-tech
1566e6759d Fail-fast when TorClientInterface deployment fails with SOCKS enabled
If any enabled interface uses SOCKS proxy and deployment fails, return
an error instead of letting RNS hit a confusing module-not-found error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:53:40 -05:00
torlando-tech
e64026e01d Address review feedback: deployment robustness, premature online, .onion UX
- Use shutil.copy2 (sibling file via __file__) as primary deployment
  method for TorClientInterface.py, with pkgutil.get_data as fallback
- Remove premature self.online = True before timeout configuration
- Prevent disabling SOCKS proxy toggle when .onion address is entered

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:53:40 -05:00
torlando-tech
892163a0cf Replace SOCKS5 monkey-patch with TorClientInterface external module
The previous socket.create_connection monkey-patch wasn't actually
intercepting Reticulum's TCP connections (RNS uses socket.connect()
directly, never create_connection). Replace with a proper RNS external
interface module that subclasses TCPClientInterface.

- Add TorClientInterface.py: overrides connect() with SOCKS5 handshake,
  uses Username/Password auth for Tor stream isolation (different
  circuits per interface), Tor-appropriate keepalive timeouts
- Remove ~175 lines of monkey-patch code from reticulum_wrapper.py
- Deploy interface to {configdir}/interfaces/ via pkgutil (RNS loads
  external interfaces from this directory)
- Config generation emits type=TorClientInterface with proxy_host/port
  when socks_proxy_enabled is set

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:53:40 -05:00
Claude
dc4946171c fix: use exact-read for SOCKS5 recv and suppress TooManyFunctions
- Replace bare sock.recv() calls with _recv_exact() helper that loops
  until all expected bytes arrive, preventing misparse when TCP delivers
  data in smaller chunks
- Parse SOCKS5 connect response in two stages: 4-byte header first,
  then variable-length bind address based on ATYP
- Add @Suppress("TooManyFunctions") to TcpClientWizardViewModel (17
  functions, threshold 15) since each function maps to a UI control

https://claude.ai/code/session_01DxBMKpvbEp6ckVEnLDb6Cv
2026-02-16 18:53:40 -05:00
Claude
2c2a7ddbac feat: add Tor/Orbot SOCKS5 proxy support for TCP connections (#392)
Enable TCP client interfaces to route connections through a SOCKS5
proxy (e.g., Orbot) for Tor .onion address support. When a user enters
a .onion hostname, the SOCKS proxy toggle auto-enables.

Changes across all layers of the stack:
- Data model: add socksProxyEnabled/Host/Port fields to TCPClient
- Serialization: JSON round-trip through DB and Python config builder
- Python wrapper: minimal SOCKS5 handshake implementation that
  monkey-patches socket.create_connection for proxied targets
- UI: "Connect via Tor (Orbot)" toggle with proxy host/port fields
  in the TCP client wizard review step
- Community servers: add interloper node .onion address

https://claude.ai/code/session_01DxBMKpvbEp6ckVEnLDb6Cv
2026-02-16 18:53:40 -05:00
Torlando
7ea41e0859
Merge pull request #458 from torlando-tech/claude/fix-icon-colors-3zIIT
fix: swap icon foreground/background color order to match LXMF standard
2026-02-14 17:44:59 -05:00
torlando-tech
f4d2076202 fix: voice call prebuffer + audio mode, quieter announce logs
- Update LXST-kt: defer playback stream start until prebuffer fills,
  set MODE_IN_COMMUNICATION for Oboe voice calls
- Reduce announce handler logging from INFO+separators to single DEBUG

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 13:12:49 -05:00
Claude
033cd88b86
fix: swap icon foreground/background color order to match LXMF standard
The LXMF icon appearance field (0x04) format used by Sideband and
MeshChat is [icon_name, fg_bytes, bg_bytes], but Columba had the
colors reversed as [icon_name, bg_bytes, fg_bytes]. This caused icons
to render with swapped colors in other LXMF clients while appearing
correct within Columba (which consistently used the wrong order for
both packing and unpacking).

Fixed all packing locations (send_lxmf_message, send_location_telemetry,
send_lxmf_message_with_method, appearance_from_marker_symbol) and all
unpacking locations (_on_lxmf_delivery, poll_received_messages,
unpack_telemetry_stream) to use the correct [name, fg, bg] order.

https://claude.ai/code/session_01XYEj7YKEJhABdHSUaXpiHy
2026-02-13 06:18:47 +00:00
torlando-tech
c92b8f6db9 fix: use correct LXMF error state threshold (0xf0, not 8)
LXMF error states are PR_NO_PATH=0xf0, PR_LINK_FAILED=0xf1,
PR_TRANSFER_FAILED=0xf2 — not sequential from 8. Use >= 0xf0 to match
the actual constant definitions from LXMRouter.py.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 22:40:54 -05:00
torlando-tech
5efd4f9b31 fix: prevent missed propagation sync completions on fast transports
On fast transports with cached paths/links, LXMF can complete sync within
milliseconds. The heartbeat loop was in 1-second idle mode and missed the
COMPLETE state entirely, leaving the UI stuck in "syncing" state.

Three coordinated fixes:
- Use -1 sentinel instead of None when resetting propagation state so the
  heartbeat immediately switches to 100ms fast-polling
- Add brief post-request polling loop (up to 2s) to catch fast completions
  before the heartbeat picks up
- Treat IDLE-during-active-sync as sync completion in PropagationNodeManager
  (handles case where COMPLETE was missed but LXMF returned to IDLE)
- Increase SharedFlow extraBufferCapacity from 1 to 5 to prevent dropping
  rapid state transitions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 21:00:14 -05:00
torlando-tech
4e12e81b14 fix: align stream appearance JSON keys/format with Kotlin parser
- Change unpack_telemetry_stream appearance keys from name/fg/bg to
  icon_name/foreground_color/background_color to match parseAppearanceJson
- Remove # prefix from hex color strings (Kotlin expects raw RRGGBB)
- Cap _pending_location_events buffer at 100 to prevent unbounded growth
- Remove accidental spec docs from PR
- Update all test assertions to match new key names and format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:40:47 -05:00
torlando-tech
71bf6b10bb fix: pass iconAppearance in collector telemetry and fix allowlist docs
- Add identityRepository to TelemetryCollectorManager so collector-bound
  telemetry includes FIELD_ICON_APPEARANCE (matching LocationSharingManager)
- Fix misleading log/comments: empty allowed_requesters set blocks all
  requests (not allows all) — code behavior was already correct
- Update TelemetryCollectorManagerTest with new constructor parameter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:06:36 -05:00
torlando-tech
e68cb96591 fix: buffer location events arriving before callback registration
Instead of dropping location events when kotlin_location_received_callback
isn't registered yet (startup race), buffer them and drain on registration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:59:03 -05:00
torlando-tech
2917428901 fix: correct FIELD_ICON_APPEARANCE byte order and AIDL nullability
Align all pack/unpack sites with Sideband wire format [name, bg, fg].
Add @nullable to AIDL icon params since they're optional.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:36:39 -05:00
torlando-tech
750ed78874 fix: detect location-only messages before callback registration
Location detection was gated on kotlin_location_received_callback being
set. Messages arriving before LocationSharingManager registered the
callback (startup race) had is_location_only=False, causing them to
appear as empty chat bubbles.

Now: field detection (FIELD_TELEMETRY, FIELD_COLUMBA_META) runs
unconditionally, only the callback invocation checks registration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:15:06 -05:00
torlando-tech
ff16eec6d4 fix: clamp accuracy to unsigned short range in pack_location_telemetry
struct.pack("!H") requires 0-65535 but coarsened locations with
approxRadius > 655m produce values exceeding this, crashing the send.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:01:16 -05:00
torlando-tech
6c8256481c fix: use appearance from telemetry message for map markers
Two bugs prevented icon rendering on Columba-to-Columba location sharing:

1. Python: location_event dict passed to kotlin_location_received_callback
   never included FIELD_ICON_APPEARANCE data — it was only parsed for the
   message callback path, not the location callback path.

2. Kotlin MapViewModel: marker icons were read exclusively from the RNS
   announce cache (announce?.iconName), ignoring the appearanceJson stored
   in ReceivedLocationEntity. Announce cache only updates on chat messages,
   so icon changes didn't propagate until a regular message was sent.

Fix: parse FIELD_ICON_APPEARANCE into location_event['appearance'] on
receive, and prefer telemetry appearance over announce data in MapViewModel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 20:54:20 -05:00
torlando-tech
ed805cd5d5 fix: attach FIELD_ICON_APPEARANCE to location telemetry messages
Columba was sending FIELD_TELEMETRY (0x02) without FIELD_ICON_APPEARANCE
(0x04) when sharing location. Sideband includes both, so Sideband icons
rendered correctly but Columba-to-Columba icons were lost.

Threads icon data through the full call chain:
- LocationSharingManager reads active identity's icon from IdentityRepository
- ReticulumProtocol.sendLocationTelemetry accepts IconAppearance param
- ServiceReticulumProtocol/Binder pass icon_name/fg/bg through AIDL
- Python send_location_telemetry attaches FIELD_ICON_APPEARANCE to LXMF fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 20:46:28 -05:00
torlando-tech
689979b93b fix: remove unused marker_symbol parameter from telemetry collector
Resolves Greptile review comment — the parameter was accepted and stored
but never passed by any caller, creating dead infrastructure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 19:30:31 -05:00
Claude
085734464a
fix: correct telemetry appearance byte order and add marker symbol registry
The Sideband FIELD_TELEMETRY_STREAM appearance format is
[icon_name, bg_rgb_bytes, fg_rgb_bytes] but the unpacker was treating
positions 1 and 2 as fg and bg respectively, swapping the colours.

- Fix appearance byte order in unpack_telemetry_stream to match Sideband
  format [icon_name, background, foreground]
- Fix FIELD_ICON_APPEARANCE constant comment to document correct order
- Allow hyphens in icon name validation for MDI names (e.g. "sail-boat")
- Add human-readable sensor logging in unpack_location_telemetry
- Add MARKER_SYMBOL_REGISTRY mapping 45 symbol keys to MDI icon names
- Add _color_from_symbol_key() for deterministic background colour
  derivation from marker symbol keys
- Add appearance_from_marker_symbol() helper for building Sideband-
  compatible appearance tuples from marker metadata
- Update _send_telemetry_stream_response to derive appearance from
  marker symbol when no explicit appearance is stored
- Update _store_telemetry_for_collector to accept marker_symbol param
- Persist appearance JSON in LocationSharingManager.handleReceivedLocation
- Update tests for corrected byte order and add marker symbol tests

Closes #405

https://claude.ai/code/session_01Y5NnRbAHQAVjfR5RezQyvm
2026-02-09 04:21:42 +00:00
torlando-tech
51a9c0db50 feat(telephony): improve call setup reliability and init speed
- Announce lxst.telephony destination alongside LXMF announces so
  remote peers discover both messaging and call paths together
- Add periodic re-announcing in CallManager (3-hour interval,
  matching reference LXST Telephony implementation)
- Auto-request identity path from network when unknown, with 5s
  retry loop (mirrors existing LXMF pattern in reticulum_wrapper)
- Move setupLxstCallManager() to first position in setupBridges()
  so Telephone is available immediately after Python init (was last,
  causing up to ~47s delay before calls could be placed)
- Remove stale "call.audio" announce handler that could never match
  the actual "lxst.telephony" aspect

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 12:43:23 -05:00
torlando-tech
1c497946b3 chore: remove dead Python LXST dependencies and audio backend
Remove vestigial Python LXST artifacts that are no longer needed
now that audio, codecs, and filters are handled by Kotlin LXST-kt:

- Remove numpy pip dependency (was for Python audio float32 conversion)
- Remove pycodec2 pip install and pre-built wheels (Kotlin JNI handles codecs)
- Delete chaquopy_audio_backend.py (617 lines, replaced by AudioDevice.kt)
- Delete lxst and lxst-filterlib wheels (never installed)
- Remove dead set_audio_bridge() plumbing from wrapper and manager
- Update call_manager.py to use renamed onInboundPacket/onInboundSignal
- Update LXST-kt submodule with transport-agnostic core/ renames

Remaining Python: call_manager.py (Reticulum bridge), rns, lxmf, u-msgpack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 16:02:34 -05:00
torlando-tech
80cfe18ffa feat(lxst): extract lxst module with audio pipeline, codecs, and telephony
Extract the LXST (voice call) stack into a standalone Gradle module
(lxst/) decoupled from the reticulum module. Includes the full audio
pipeline (LineSink, LineSource, Mixer, Packetizer, Pipeline), codec
wrappers (Opus with 16kHz decode-rate cap for wuqi-opus 1024-sample
limit, Codec2), bridge layer (KotlinAudioBridge with 500ms AudioTrack
buffer floor, NetworkPacketBridge, CallBridge), and telephony state
machine (Telephone, Profile, NetworkTransport interface).

LineSink improvements:
- Monotonic clock pacer eliminates cumulative drift from relative delays
- Post-underrun re-buffering (AUTOSTART_MIN frames) prevents rapid
  micro-underrun cycles that caused audible pops
- Underrun duration threshold: brief glitches (<2 frame periods) resume
  immediately, sustained gaps trigger full re-buffer
- MAX_FRAMES increased to 15 (900ms jitter absorption at 60ms/frame)

Test coverage:
- LineSinkPacingTest: 9 unit tests for monotonic clock, burst pacing,
  drift, underrun recovery, re-buffer behavior
- LineSinkRebufferInstrumentedTest: 5 hardware tests validating
  re-buffer strategy against real AudioTrack underrun counts
- OpusDecodeRateInstrumentedTest: 8 tests documenting wuqi-opus
  1024-sample buffer constraint and 16kHz decode cap
- LineSinkPacingInstrumentedTest, FullDuplexInstrumentedTest,
  LineSourceCaptureInstrumentedTest: hardware validation suite

Known limitations:
- RX delayed ~2-3s (16kHz decode → 60ms frames → large pre-buffer)
- Occasional TX pops (separate from RX re-buffer work)
- Fix requires replacing wuqi-opus with caller-allocated-buffer library

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 16:02:33 -05:00
torlando-tech
1d0cf79f0a feat(11.6): enable bidirectional voice calls with crash fixes
Wire Kotlin→Python audio transmit path by registering call_manager as
NetworkPacketBridge's pythonNetworkHandler. Fix wuqi-opus SIGSEGV by
capping decode sample rate to fit 1024-sample buffer. Fix LineSink
sample rate mismatch and dual-sink race condition. Re-enable full
transmit pipeline (Packetizer, Mixer, LineSource). Add jarray→bytes
conversion for Chaquopy type compatibility.

Key changes:
- PythonWrapperManager: register setPythonNetworkHandler after CallManager init
- Opus: compute safe decode sample rate for wuqi-opus buffer limit
- LineSink: add releasedFlag to prevent stale frame auto-restart
- Telephone: re-enable transmit pipeline, fix pipeline lifecycle
- NetworkPacketBridge: add diagnostic logging for consumer coroutine
- call_manager.py: add jarray→bytes conversion, diagnostic logging
- LinkSource: add packet decoding with codec header parsing
- Remove obsolete lxst_debug_instrumentation.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 16:02:33 -05:00
torlando-tech
b53df88c45 feat(10-05): initialize NetworkPacketBridge in PythonWrapperManager
- Add NetworkPacketBridge import
- Add networkPacketBridge instance variable
- Initialize NetworkPacketBridge in setupCallManager()
- Pass bridge to Python via set_network_bridge()
- Add shutdown cleanup for networkPacketBridge
- Add set_network_bridge() method to reticulum_wrapper.py
- Pass kotlin_network_bridge to initialize_call_manager()
2026-02-07 16:02:33 -05:00
torlando-tech
86252a908e fix(python): make display_name optional in create_identity()
The second create_identity() method at line 7376 shadows the first one at
line 2338. Making display_name optional allows callers that don't pass a
name to work correctly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 10:31:56 -05:00
torlando-tech
9355889a31 feat(05-01): add Python memory profiler module
- Create memory_profiler.py with tracemalloc snapshot comparison
- Add enable_memory_profiling() method to ReticulumWrapper
- Schedule periodic snapshots using threading.Timer (Chaquopy-compatible)
- Filter frozen importlib and unknown traces to reduce noise
- Log top 10 growing allocations to Android logcat via logging_utils
- Provide get_memory_profile() for current stats query
- Zero overhead when disabled (lazy import pattern)
2026-01-29 17:08:16 -05:00
Torlando
c0529dc307
Merge pull request #284 from torlando-tech/feature/issue-216-rns-discovery
feat: add RNS 1.1.x bootstrap and interface discovery support
2026-01-22 13:48:06 -05:00
torlando-tech
53fa9f24e0 feat: add connected indicator and improved icons for discovered interfaces
- Add "Connected" badge showing which discovered interfaces are currently
  auto-connected by RNS discovery
- Add getAutoconnectedEndpoints() API to fetch active auto-connected interfaces
- Use type-specific icons: globe for TCP, antenna for radio, incognito for I2P,
  tree-pine for Yggdrasil (detected via 0200::/7 IPv6 range)
- Show I2P b32 addresses with .b32.i2p suffix
- Display human-readable interface type labels (e.g., "Backbone (TCP)")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:12:05 -05:00
torlando-tech
8bc1d054d4 feat: add discovery toggle and fix discovered interfaces display
- Add toggle in Discovered Interfaces screen to enable/disable discovery
- Service auto-restarts when toggle is changed (no app restart needed)
- Show bootstrap-enabled interface names in settings card
- Add discovery settings to SettingsRepository and StartupConfigLoader
- Include discover_interfaces and autoconnect_discovered_interfaces in config
- Include bootstrap_only for TCPClient interfaces in buildConfigJson
- Fix Python wrapper bug: discovered_interfaces() returns list, not dict
- Add bottom padding to list to avoid nav bar overlap

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:49:16 -05:00
torlando-tech
66982b18de feat: Show user-configured interface name in Node Details
Update the "Received Via" card in Node Details to show the user-configured
interface name (e.g., "Sideband Server") instead of generic type names
(e.g., "TCP/IP").

Python changes:
- Build formatted interface string "ClassName[UserConfiguredName]" from
  the interface object's type and .name attribute
- This allows Kotlin to extract both the friendly name and interface type

Kotlin changes:
- Add extractFriendlyName() to parse user-configured name from brackets
- Add extractInterfaceType() to parse class name before brackets
- Display friendly name as main text, interface type as subtitle

The card now shows:
- Title: "Received Via"
- Content: "Sideband Server" (user-configured name)
- Subtitle: "TCPClientInterface" (interface type)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:02:43 -05:00
torlando-tech
93d794c1fd feat: extend DiscoveredInterface data model with full RNS 1.1.x fields
Add comprehensive discovery data to DiscoveredInterface including:
- Transport/network IDs and status info (statusCode, lastHeard, hops)
- TCP-specific fields (reachableOn, port)
- Radio-specific fields (frequency, bandwidth, SF, CR, modulation)
- Location fields (latitude, longitude, height)
- Helper properties for interface type detection

Update Python bridge to return full discovery data from RNS 1.1.x API.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:11:18 -05:00
torlando-tech
e0dae212dc feat: add RNS 1.1.x bootstrap and interface discovery support (#216)
Add support for RNS 1.1.0+ interface discovery and bootstrap features,
enabling new users to connect without relying on deprecated public
infrastructure.

Changes:
- Add discovery settings to ReticulumConfig (discoverInterfaces,
  autoconnectDiscoveredInterfaces, interfaceDiscoverySources,
  requiredDiscoveryValue)
- Add bootstrapOnly option to TCPClient interface config
- Update Python config generation for discovery and bootstrap options
- Add get_discovered_interfaces() and is_discovery_enabled() API methods
- Extend AIDL interface with discovery methods
- Mark 3 reliable community servers as bootstrap candidates (Beleth,
  Quad4, FireZen)
- Add bootstrap toggle to TCP Client wizard UI

Note: The RNS fork needs to be rebased on 1.1.2 to enable the actual
discovery features. The code is ready but awaiting the dependency update.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 16:45:38 -05:00
Torlando
4af51e7c8a
Merge pull request #311 from torlando-tech/feature/issue-215-telemetry-collector-api
Add telemetry collector API with group tracking features
2026-01-21 13:49:52 -05:00