- Add meshcore_device_name field to InterfaceSettings
- Implement set_name() method in device interface (real and mock)
- Update receiver to set device name during initialization if configured
- Add --device-name CLI option with MESHCORE_DEVICE_NAME env var support
- Device name is set after time sync and before advertisement broadcast
Fixes#37🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
Changed the startup advertisement from flood=False to flood=True
so that the device name is broadcast to the mesh network.
Fixes#38
Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
Update map node labels to show the full display name (friendly_name tag
→ advertised node name → public key prefix) instead of just the 2-char
public key prefix. This makes node labels consistent with the rest of
the site and easier to identify at a glance.
The backend already computes the correct display name in map.py:96-101,
so this change just uses that computed name in the label.
Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
Display relative time since last seen (e.g., '2m', '1h', '2d') in node
labels on the map page. This makes it easier to quickly identify how
recently nodes were active without opening the popup.
- Add formatRelativeTime() function to calculate time difference
- Update createNodeIcon() to include relative time in label
- Adjust icon size to accommodate additional text
- Format: keyPrefix (timeAgo) e.g., 'ab (5m)'
Fixes#33
Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
Fixed parse error when clicking the filter button on messages screen
with "All Channels" selected. The form was sending an empty string
for channel_idx, but FastAPI expected either a valid integer or None.
Changes:
- Accept channel_idx as string in query parameter
- Parse and validate channel_idx before passing to API
- Treat empty strings as None to prevent validation errors
- Add error handling for invalid integer values
Fixes#25
Co-authored-by: JingleManSweep <jinglemansweep@users.noreply.github.com>
Replace presentation-layer deduplication with collector-level approach:
- Add event_hash column to messages, advertisements, trace_paths, telemetry tables
- Handlers compute content hashes and skip duplicate events at insertion time
- Use 5-minute time buckets for advertisements and telemetry
- Include Alembic migration for schema changes
When multiple receiver nodes are running, the same mesh events (messages,
advertisements) are reported multiple times. This causes duplicate entries
in the Web UI.
Changes:
- Add hash_utils.py with deterministic hash functions for each event type
- Add `dedupe` parameter to messages and advertisements API endpoints (default: True)
- Update dashboard stats to use distinct counts for messages/advertisements
- Deduplicate recent advertisements and channel messages in dashboard
- Add comprehensive tests for hash utilities
Hash strategy:
- Messages: hash of text + pubkey_prefix + channel_idx + sender_timestamp + txt_type
- Advertisements: hash of public_key + name + adv_type + flags + 5-minute time bucket
Members can now have multiple associated nodes, each with a public_key
and node_role (e.g., 'chat', 'repeater'). This replaces the single
public_key field on members with a one-to-many relationship.
Changes:
- Add MemberNode model for member-node associations
- Update Member model to remove public_key, add nodes relationship
- Update Pydantic schemas with MemberNodeCreate/MemberNodeRead
- Update member_import.py to handle nodes list in seed files
- Update API routes to handle nodes in create/update/read operations
- Add Alembic migration to create member_nodes table and migrate data
- Update example seed file with new format
Replace the channel counts table with actual recent messages per channel:
- Added ChannelMessage schema for channel message summaries
- Dashboard API now fetches latest 5 messages for each channel with sender name lookups
- Network page displays messages grouped by channel with sender names and timestamps
- Only shows channels that have messages
The adv_type from the Advertisement record is often null, but the linked
Node has the correct adv_type. Now falls back to source_node.adv_type
when adv.adv_type is null.
- Swap Time and Type columns (Type now first)
- Add receiver_name and receiver_friendly_name to MessageRead schema
- Update messages API to fetch receiver node names and tags
- Make Receiver column a link showing name with public key prefix
- Rename Name column to Node
- Remove separate Public Key column
- Show name with public key prefix below (like Advertisements list)
- Add whitespace-nowrap to Last Seen column
- Join with Node table to get node names and tags for both source
and receiver nodes
- Display friendly_name (from tags), node_name, or advertised name
with priority in that order
- Show name with public key preview for both Node and Received By columns
- Remove Name and Type columns (usually null)
- Reorder columns: Node first, then Received By, then Time
- Link both Node and Received By to their node detail pages
- Show node name with public key preview when available
- Reduce hero section size and add stats bar with node/message counts
- Add new Advertisements page with public key filtering
- Update hero navigation buttons: Dashboard, Nodes, Advertisements, Messages
- Add Advertisements to main navigation menu
- Remove Hops column from messages list (always empty)
- Display full message text with proper multi-line wrapping
Internal database UUIDs (id, node_id, receiver_node_id) were being
exposed in API responses. These are implementation details that should
not be visible to API consumers. The canonical identifier for nodes
is the 64-char hex public_key.
Changes:
- Remove id, node_id from NodeTagRead, NodeRead schemas
- Remove id from MemberRead schema
- Remove id, receiver_node_id, node_id from MessageRead, AdvertisementRead,
TracePathRead, TelemetryRead schemas
- Update web map component to use public_key instead of member.id
for owner filtering
- Update tests to not assert on removed fields
- Return total_nodes, nodes_with_coords, and error in response
- Display meaningful messages when no nodes or no coordinates found
- Log API errors and node counts for debugging
- Use inline styles for marker colors instead of CSS classes for reliable rendering
- Center map on node locations when data is first loaded
- Refactor filter logic to separate recentering behavior
- Update legend to use inline styles
- Enhanced /map/data endpoint to include node role tag and member ownership
- Added client-side filtering for node type (chat, repeater, room)
- Added toggle to filter for infrastructure nodes only (role: infra)
- Added dropdown filter for member owner (nodes linked via public_key)
- Color-coded markers by node type with gold border for infrastructure
- Added legend showing marker types
- Dynamic count display showing total vs filtered nodes