MeshCore encodes lat/lon as little-endian signed int32 divided by 1e6,
not as IEEE 754 floats. This caused all map pins to show at (0,0).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Discard NaN, Infinity, and out-of-range lat/lon values from
struct.unpack to prevent JSON parse errors in browser.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract lat/lon from advert payloads (struct unpack from binary)
- Store type_label and lat/lon in cache from device seed and adverts
- Show Map button for cache contacts with GPS coordinates
- Show colored type badge (CLI/REP/ROOM/SENS) for typed cache contacts
- Type filter now works for cache contacts with known type
- Change counter label from "known" to "cached"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces two sort toggle buttons with a single <select> dropdown (e-commerce style)
so all 3 filter/sort controls fit on mobile screens.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contacts cache accumulates all known node names from device contacts
and adverts into a JSONL file, so @mentions work even after contacts
are removed from the device. Background thread scans adverts every
45s and parses advert payloads to extract public keys and node names.
Existing Contacts page now shows merged view with "Cache" badge for
contacts not on device, plus source filter (All/On device/Cache only).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bi-flask was added in Bootstrap Icons 1.12+, but project uses 1.11.2.
Replace with bi-clipboard-data which is available and conveys
"data analysis".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generate analyzer_url from computed pkt_payload for all incoming
channel messages, not just those with echo path matches. This means
the analyzer button appears even when no route paths were captured.
Also change analyzer button icon from bi-search (magnifying glass)
to bi-flask (lab flask) to better convey "analysis/inspection".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The parser's .strip() was removing trailing whitespace from message
text, but the encrypted radio payload includes those trailing spaces.
This caused pkt_payload mismatches for messages ending with spaces
(e.g., "Dzień dobry "). Use original unstripped text for raw_text.
Also add debug logging for unmatched messages to help diagnose
remaining edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unreliable timestamp-based heuristic (±10s window) with exact
cryptographic matching for incoming channel message routes. Compute
pkt_payload by reconstructing the AES-128-ECB encrypted packet from
message data (sender_timestamp, txt_type, text) + channel secret, then
match against echo data by exact key lookup.
Also accumulate ALL route paths per message (previously only last path
was kept due to dict overwrite), and display them in a multi-path popup
showing SNR and hops for each route.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clickable "?" icon on DMs without ACK, showing a popup
explaining that delivery is unknown (mobile-friendly).
Update README, user guide with new features (Analyzer links,
DM delivery tracking).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stop scheduling further post-send reloads as soon as the last
own message shows a delivery checkmark.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add two extra delayed reloads (6s, 15s) after sending a DM,
matching the channel chat pattern, so ACK checkmarks appear
without needing to send another message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bridge captures ACK packets from meshcli stdout (json_log_rx),
persists to .acks.jsonl, and exposes /ack_status endpoint.
Delivery status is merged server-side into DM messages and
displayed as a green checkmark with SNR/route tooltip.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compute packet_hash from pkt_payload (SHA-256 of type byte + payload)
and generate analyzer.letsmesh.net links. Button appears on both sent
and received messages when echo data is available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prompt lines (DeviceName|* ...) and summary lines (> N contacts)
are normal meshcli output, not format changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The script runs from host piped into the container, so argparse
doesn't work with stdin. Use env vars (BRIDGE_URL, FULL) as primary
config with fallback CLI arg parsing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diagnostic tool that tests all meshcli commands and response formats
used by mc-webui against a running bridge instance, detecting breaking
changes early when updating meshcore-cli versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When MC_DEVICE_NAME=auto, the bridge initially creates log files as
auto.adverts.jsonl and auto.echoes.jsonl. After detecting the real
device name, it now renames them and updates paths. Also adds
echoes_log to the /health endpoint.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The background thread now retries with exponential backoff (5s→60s)
instead of giving up after 3 attempts. Also accepts detected device
name from bridge even when bridge health status is unhealthy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Documented the bridge crash-loop scenario where the MeshCore device
serial port connects but firmware doesn't respond to commands,
including symptoms, what doesn't help, and the fix (re-flash firmware).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tooltips don't work on touchscreens. Added a popup that appears on
tap/click, shows the full path, and auto-dismisses after 4 seconds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Deduplicate 2-char repeater codes in echo badge (same repeater via
different routes was shown twice, e.g., "3 (d1, 5e, 5e)")
- Use deduplicated count for unique repeaters, not unique full paths
- Improve incoming path correlation: widen window to 10s, prefer
path_len match but fall back to timestamp-only if needed
- Add debug logging for incoming path correlation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show repeater path codes in sent message echo badge (e.g., "2 (5e, d1)")
- Capture and display route path for incoming messages in message meta
- Persist all echo data to .echoes.jsonl (survives container restarts)
- Load echo data from disk on startup with 7-day retention and compaction
- Combine sent echo and incoming path data in single /echo_counts response
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sender name above outgoing messages in group chat
- Display emoji-only messages in larger font size
- Fix leading space before text in quoted replies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-detect #channel names in messages and convert to clickable links
- Click existing channel: switch to it via channel selector
- Click non-existing channel: join via API, then switch
- Green styling to distinguish from blue @mentions
- Only active in channel context (not in DMs)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add filter-utils.js with diacritic-insensitive search and text highlighting
- Add FAB filter button (gray funnel icon) to channel chat and DM
- Filter bar slides in as overlay at top of chat area
- Real-time filtering with debounce (150ms) as user types
- Matched text highlighted with yellow background
- Support for Polish characters (wol matches wół)
- Keyboard shortcuts: Ctrl+F to open, Escape to close
- Match counter shows X / Y filtered messages
- Filter persists during auto-refresh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added AUTO_START option (default: true) to automatically start
stopped containers, not just restart unhealthy ones
- Added handle_stopped_container() function
- Updated documentation with new configuration option
Set AUTO_START=false to disable automatic starting of stopped containers.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added docs/watchdog.md with installation and usage guide
- Added watchdog reference to README.md documentation table
- Fixed executable permissions on watchdog scripts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New systemd service that monitors Docker containers and automatically
restarts unhealthy ones. Features:
- Checks container health every 30 seconds
- Captures logs before restart for diagnostics
- Saves diagnostic files to /tmp/mc-webui-watchdog-*.log
- HTTP status endpoint on port 5051
- Restart history tracking
Install with: sudo ./scripts/watchdog/install.sh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added 'Connection: close' header to bridge requests to prevent
connection pooling issues when running from APScheduler background
thread context.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes "Broken pipe" errors on slower hardware (single CPU) by:
- Adding 0.5s delay between contact deletions
- Retrying failed deletions up to 2 times with longer delay
- Special handling for Broken pipe errors
This prevents overwhelming meshcore-bridge on resource-constrained systems.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added "Echo tracking" to Key Features section
- Added "Echo Tracking" to Completed Features checklist
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Echo counts weren't appearing until sending another message because
auto-refresh only triggers when new messages arrive. Added 6s and 15s
delayed reloads after sending to catch echoes as they arrive.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Track how many repeaters heard and forwarded sent channel messages,
similar to the Meshcore mobile app's "Heard X repeats" feature.
- Bridge: Detect GRP_TXT echoes from stdout, track unique paths
- Bridge: New /register_echo and /echo_counts API endpoints
- API: Register messages for echo tracking after send
- API: Merge echo counts into /api/messages response
- Frontend: Display green badge with broadcast icon next to Resend button
- CSS: Echo badge styling with dark mode support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add server-side API for console history (GET/POST/DELETE)
- Add history dropdown button with clock icon
- Save commands to server after execution
- Load history from server on page load
- History persists between sessions and works across devices
- Max 50 commands stored, duplicates moved to end
- Dropdown shows most recent commands first
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added req_status, req_neighbours, and trace commands with 15s timeout
as they communicate with repeaters and need time for responses.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Strip leading whitespace before checking if line starts with '{' to
ensure JSON packet lines are properly filtered regardless of indentation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The werkzeug development server produces "write() before start_response"
errors during WebSocket upgrade. These are cosmetic - the connection
still works via Socket.IO retry. Added a logging filter to suppress
these errors for cleaner logs.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
JSON lines with payload_typename (internal mesh protocol data like
CONTROL packets) are now filtered out from console output, showing
only the human-readable results.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Commands like node_discover that take 10-15 seconds without producing
any intermediate output were being marked as completed after 300ms of
silence, resulting in "(no output)" being shown to the user.
Now the monitor waits for at least 80% of the command timeout before
applying the silence detection, ensuring slow commands have time to
complete and return their results.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Semi-transparent button appears when user scrolls up
- Positioned at bottom-right of messages container
- Clicking scrolls to latest messages and hides button
- Smooth fade-in/out animation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>