mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-03-28 17:42:45 +01:00
feat: Add MeshCore Analyzer link button to channel messages
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>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
REST API endpoints for mc-webui
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import json
|
||||
import re
|
||||
@@ -33,6 +34,20 @@ _contacts_detailed_cache_timestamp = 0
|
||||
CONTACTS_DETAILED_CACHE_TTL = 60 # seconds
|
||||
|
||||
|
||||
ANALYZER_BASE_URL = 'https://analyzer.letsmesh.net/packets?packet_hash='
|
||||
GRP_TXT_TYPE_BYTE = 0x05
|
||||
|
||||
|
||||
def compute_analyzer_url(pkt_payload):
|
||||
"""Compute MeshCore Analyzer URL from a hex-encoded pkt_payload."""
|
||||
try:
|
||||
raw = bytes([GRP_TXT_TYPE_BYTE]) + bytes.fromhex(pkt_payload)
|
||||
packet_hash = hashlib.sha256(raw).hexdigest()[:16].upper()
|
||||
return f"{ANALYZER_BASE_URL}{packet_hash}"
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
|
||||
|
||||
def get_channels_cached(force_refresh=False):
|
||||
"""
|
||||
Get channels with caching to reduce USB/meshcli calls.
|
||||
@@ -321,6 +336,9 @@ def get_messages():
|
||||
abs(msg['timestamp'] - ec['timestamp']) < 5):
|
||||
msg['echo_count'] = ec['count']
|
||||
msg['echo_paths'] = ec.get('paths', [])
|
||||
pkt = ec.get('pkt_payload')
|
||||
if pkt:
|
||||
msg['analyzer_url'] = compute_analyzer_url(pkt)
|
||||
break
|
||||
|
||||
# Merge incoming paths into received messages
|
||||
@@ -342,6 +360,9 @@ def get_messages():
|
||||
best_delta = delta
|
||||
if best_match:
|
||||
msg['path'] = best_match['path']
|
||||
pkt = best_match.get('pkt_payload')
|
||||
if pkt:
|
||||
msg['analyzer_url'] = compute_analyzer_url(pkt)
|
||||
except Exception as e:
|
||||
logger.debug(f"Echo data fetch failed (non-critical): {e}")
|
||||
|
||||
|
||||
@@ -746,6 +746,11 @@ function createMessageElement(msg) {
|
||||
<div class="message-content">${processMessageContent(msg.content)}</div>
|
||||
<div class="message-actions justify-content-end">
|
||||
${echoDisplay}
|
||||
${msg.analyzer_url ? `
|
||||
<button class="btn btn-outline-secondary btn-msg-action" onclick="window.open('${msg.analyzer_url}', 'meshcore-analyzer')" title="View in Analyzer">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
<button class="btn btn-outline-secondary btn-msg-action" onclick='resendMessage(${JSON.stringify(msg.content)})' title="Resend">
|
||||
<i class="bi bi-arrow-repeat"></i>
|
||||
</button>
|
||||
@@ -785,6 +790,11 @@ function createMessageElement(msg) {
|
||||
<i class="bi bi-geo-alt"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
${msg.analyzer_url ? `
|
||||
<button class="btn btn-outline-secondary btn-msg-action" onclick="window.open('${msg.analyzer_url}', 'meshcore-analyzer')" title="View in Analyzer">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1274,11 +1274,11 @@ def get_echo_counts():
|
||||
{
|
||||
"success": true,
|
||||
"echo_counts": [
|
||||
{"timestamp": 1706500000.123, "channel_idx": 0, "count": 3, "paths": ["5e", "d1", "a3"]},
|
||||
{"timestamp": 1706500000.123, "channel_idx": 0, "count": 3, "paths": ["5e", "d1", "a3"], "pkt_payload": "abcd..."},
|
||||
...
|
||||
],
|
||||
"incoming_paths": [
|
||||
{"timestamp": 1706500000.456, "path": "8a40a605", "path_len": 4, "snr": 11.0},
|
||||
{"timestamp": 1706500000.456, "path": "8a40a605", "path_len": 4, "snr": 11.0, "pkt_payload": "efgh..."},
|
||||
...
|
||||
]
|
||||
}
|
||||
@@ -1293,7 +1293,8 @@ def get_echo_counts():
|
||||
'timestamp': data['timestamp'],
|
||||
'channel_idx': data['channel_idx'],
|
||||
'count': len(data['paths']),
|
||||
'paths': list(data['paths'])
|
||||
'paths': list(data['paths']),
|
||||
'pkt_payload': pkt_payload,
|
||||
})
|
||||
|
||||
incoming = []
|
||||
@@ -1303,6 +1304,7 @@ def get_echo_counts():
|
||||
'path': data['path'],
|
||||
'path_len': data.get('path_len'),
|
||||
'snr': data.get('snr'),
|
||||
'pkt_payload': pkt_payload,
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
|
||||
Reference in New Issue
Block a user