v1.0.23: Show node public hash in WiFi config portal
Add Reticulum destination hash indicator at the top of the captive-portal config page so users can identify the device. - Store the 32-char hex destination hash in RTC_NOINIT memory after RNS starts on a normal boot (survives software reboots into config mode) - BoundaryConfig.h reads the RTC value and renders a styled hash box at the top of the HTML page, above the config form - Falls back to a friendly placeholder if the device has never completed a normal boot (hash not yet assigned) - Rebuild precompiled firmware for Heltec V3 and V4 boundary variants
This commit is contained in:
@@ -24,6 +24,11 @@
|
|||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
|
|
||||||
|
// ─── Node hash (cached in RTC by normal boot, read here without starting RNS) ─
|
||||||
|
#define NODE_HASH_RTC_MAGIC 0x504B4841UL
|
||||||
|
extern uint32_t rtc_node_hash_magic;
|
||||||
|
extern char rtc_node_hash_hex[33];
|
||||||
|
|
||||||
// ─── Config Portal State ─────────────────────────────────────────────────────
|
// ─── Config Portal State ─────────────────────────────────────────────────────
|
||||||
static bool config_portal_active = false;
|
static bool config_portal_active = false;
|
||||||
static WebServer* config_server = nullptr;
|
static WebServer* config_server = nullptr;
|
||||||
@@ -126,12 +131,25 @@ static void config_send_html() {
|
|||||||
"button:hover{background:#c73e54;}"
|
"button:hover{background:#c73e54;}"
|
||||||
".ok{background:#16213e;padding:20px;border-radius:8px;text-align:center;}"
|
".ok{background:#16213e;padding:20px;border-radius:8px;text-align:center;}"
|
||||||
".ok h1{color:#0f0;}"
|
".ok h1{color:#0f0;}"
|
||||||
|
".node-hash{background:#0f1a30;border:1px solid #0f3460;border-radius:6px;"
|
||||||
|
"padding:10px 14px;margin:0 0 16px;}"
|
||||||
|
".node-hash .nh-label{display:block;font-size:0.75em;color:#888;margin-bottom:4px;}"
|
||||||
|
".node-hash code{font-family:monospace;font-size:0.95em;color:#7ecfff;"
|
||||||
|
"word-break:break-all;letter-spacing:0.05em;}"
|
||||||
"</style></head><body>"
|
"</style></head><body>"
|
||||||
"<h1>📡 RNode Boundary Node</h1>"
|
"<h1>📡 RNode Boundary Node</h1>"
|
||||||
"<form method='POST' action='/save'>"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── WiFi STA Section ──
|
// ── Node public hash ──
|
||||||
|
html += F("<div class='node-hash'><span class='nh-label'>🔑 Node Hash (Reticulum destination)</span><code>");
|
||||||
|
if (rtc_node_hash_magic == NODE_HASH_RTC_MAGIC && rtc_node_hash_hex[0] != '\0') {
|
||||||
|
html += String(rtc_node_hash_hex);
|
||||||
|
} else {
|
||||||
|
html += F("<span style='color:#888;font-style:italic;'>Not yet assigned — will be set on first normal boot</span>");
|
||||||
|
}
|
||||||
|
html += F("</code></div>");
|
||||||
|
|
||||||
|
html += F("<form method='POST' action='/save'>");
|
||||||
html += F(
|
html += F(
|
||||||
"<h2>📶 WiFi Network</h2>"
|
"<h2>📶 WiFi Network</h2>"
|
||||||
"<label>WiFi</label>"
|
"<label>WiFi</label>"
|
||||||
|
|||||||
@@ -259,6 +259,13 @@ RTC_NOINIT_ATTR uint32_t boundary_skip_config;
|
|||||||
RTC_NOINIT_ATTR uint32_t bootloop_magic;
|
RTC_NOINIT_ATTR uint32_t bootloop_magic;
|
||||||
RTC_NOINIT_ATTR uint32_t bootloop_count;
|
RTC_NOINIT_ATTR uint32_t bootloop_count;
|
||||||
RTC_NOINIT_ATTR uint32_t bootloop_first_boot_ms;
|
RTC_NOINIT_ATTR uint32_t bootloop_first_boot_ms;
|
||||||
|
|
||||||
|
// Node public hash — cached in RTC so the config portal can display it without
|
||||||
|
// needing to start RNS. Populated after the transport destination is created
|
||||||
|
// on a normal boot; survives software reboots into the captive portal.
|
||||||
|
#define NODE_HASH_RTC_MAGIC 0x504B4841UL // "PKHA"
|
||||||
|
RTC_NOINIT_ATTR uint32_t rtc_node_hash_magic;
|
||||||
|
RTC_NOINIT_ATTR char rtc_node_hash_hex[33]; // 32 hex chars + NUL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // HAS_RNS
|
#endif // HAS_RNS
|
||||||
@@ -927,6 +934,17 @@ void setup() {
|
|||||||
*/
|
*/
|
||||||
RNS::Destination destination(RNS::Transport::identity(), RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");
|
RNS::Destination destination(RNS::Transport::identity(), RNS::Type::Destination::IN, RNS::Type::Destination::SINGLE, "rnstransport", "local");
|
||||||
|
|
||||||
|
// Cache this node's destination hash in RTC memory so the captive-portal
|
||||||
|
// config page can show it without needing RNS to be running.
|
||||||
|
{
|
||||||
|
std::string h = destination.hash().toHex();
|
||||||
|
size_t len = h.length();
|
||||||
|
if (len > 32) len = 32;
|
||||||
|
memcpy(rtc_node_hash_hex, h.c_str(), len);
|
||||||
|
rtc_node_hash_hex[len] = '\0';
|
||||||
|
rtc_node_hash_magic = NODE_HASH_RTC_MAGIC;
|
||||||
|
}
|
||||||
|
|
||||||
HEAD("RNS is READY!", RNS::LOG_TRACE);
|
HEAD("RNS is READY!", RNS::LOG_TRACE);
|
||||||
#ifdef BOUNDARY_MODE
|
#ifdef BOUNDARY_MODE
|
||||||
HEAD("*** BOUNDARY MODE ACTIVE ***", RNS::LOG_TRACE);
|
HEAD("*** BOUNDARY MODE ACTIVE ***", RNS::LOG_TRACE);
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user