Add transport mode notes and config updates
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
// Copyright (C) 2026, Boundary Mode Extension
|
||||
// Based on microReticulum_Firmware by Mark Qvist
|
||||
//
|
||||
// BoundaryConfig.h — Captive-portal web configuration for Boundary Mode.
|
||||
// BoundaryConfig.h — Captive-portal web configuration for the legacy
|
||||
// "Boundary Mode" path. This should be renamed to "Transport Mode"
|
||||
// together with the rest of the boundary-mode terminology. In this fork,
|
||||
// transport/boundary mode is the only intended mode of operation.
|
||||
// When triggered (first boot with no config, or button hold >5s),
|
||||
// the device starts a WiFi AP with a web form for all settings:
|
||||
// WiFi STA credentials, TCP backbone params, LoRa radio params,
|
||||
@@ -59,6 +62,16 @@ static const char* const BW_OPTIONS_LABELS[] PROGMEM = {
|
||||
};
|
||||
static const int BW_OPTIONS_COUNT = sizeof(BW_OPTIONS_HZ) / sizeof(BW_OPTIONS_HZ[0]);
|
||||
|
||||
static uint8_t config_default_display_rotation() {
|
||||
#if BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_RAK4631
|
||||
return 0;
|
||||
#elif BOARD_MODEL == BOARD_HELTEC32_V2 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TBEAM_S_V1
|
||||
return 1;
|
||||
#else
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ─── HTML Page Generation ────────────────────────────────────────────────────
|
||||
|
||||
static void config_send_html() {
|
||||
@@ -304,6 +317,11 @@ static void config_send_html() {
|
||||
cur_blank = EEPROM.read(eeprom_addr(ADDR_CONF_DBLK));
|
||||
}
|
||||
|
||||
uint8_t cur_rotation = EEPROM.read(eeprom_addr(ADDR_CONF_DROT));
|
||||
if (cur_rotation > 3) {
|
||||
cur_rotation = config_default_display_rotation();
|
||||
}
|
||||
|
||||
static const uint8_t blank_vals[] = { 0, 1, 5, 10, 30, 60 };
|
||||
static const char* blank_labels[] = { "Never", "1 minute", "5 minutes", "10 minutes", "30 minutes", "60 minutes" };
|
||||
static const int blank_count = 6;
|
||||
@@ -320,6 +338,23 @@ static void config_send_html() {
|
||||
html += F("</select>");
|
||||
html += F("<p class='note'>Turn off display after inactivity to save power</p>");
|
||||
|
||||
html += F("<label>Display Orientation</label><select name='disp_rot'>");
|
||||
html += F("<option value='0'");
|
||||
if (cur_rotation == 0) html += F(" selected");
|
||||
html += F(">Landscape</option>");
|
||||
html += F("<option value='1'");
|
||||
if (cur_rotation == 1) html += F(" selected");
|
||||
html += F(">Portrait</option>");
|
||||
html += F("<option value='2'");
|
||||
if (cur_rotation == 2) html += F(" selected");
|
||||
html += F(">Landscape Flipped</option>");
|
||||
html += F("<option value='3'");
|
||||
if (cur_rotation == 3) html += F(" selected");
|
||||
html += F(">Portrait Flipped</option>");
|
||||
html += F("</select>");
|
||||
html += F("<p class='note'>Choose the orientation that matches your OLED mounting. "
|
||||
"Landscape modes place the two status panes side by side; portrait modes stack them.</p>");
|
||||
|
||||
// ── Submit ──
|
||||
html += F(
|
||||
"<button type='submit'>Save & Reboot</button>"
|
||||
@@ -353,6 +388,14 @@ static void config_handle_save() {
|
||||
// Set WiFi mode to STA
|
||||
EEPROM.write(eeprom_addr(ADDR_CONF_WIFI), WR_WIFI_STA);
|
||||
|
||||
// Boundary mode always uses DHCP on the STA interface. Clear the legacy
|
||||
// static IP and netmask slots so stale values from older firmware or tools
|
||||
// cannot force a persistent static address.
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EEPROM.write(config_addr(ADDR_CONF_IP + i), 0x00);
|
||||
EEPROM.write(config_addr(ADDR_CONF_NM + i), 0x00);
|
||||
}
|
||||
|
||||
// ── WiFi enable setting ──
|
||||
boundary_state.wifi_enabled = (config_server->arg("wifi_en").toInt() == 1);
|
||||
|
||||
@@ -370,6 +413,12 @@ static void config_handle_save() {
|
||||
eeprom_update(eeprom_addr(ADDR_CONF_DBLK), blank_val);
|
||||
}
|
||||
|
||||
int display_rotation = config_server->arg("disp_rot").toInt();
|
||||
if (display_rotation < 0 || display_rotation > 3) {
|
||||
display_rotation = config_default_display_rotation();
|
||||
}
|
||||
eeprom_update(eeprom_addr(ADDR_CONF_DROT), (uint8_t)display_rotation);
|
||||
|
||||
// ── TCP backbone settings ──
|
||||
boundary_state.tcp_mode = (uint8_t)config_server->arg("tcp_mode").toInt(); // 0=disabled, 1=client
|
||||
if (boundary_state.tcp_mode > 1) boundary_state.tcp_mode = 0;
|
||||
@@ -481,6 +530,14 @@ static void config_handle_redirect() {
|
||||
|
||||
// ─── Check if config is needed ───────────────────────────────────────────────
|
||||
bool boundary_needs_config() {
|
||||
// If the RTNode app marker is missing, this node was either never
|
||||
// configured by RTNode or was flashed from a different firmware family
|
||||
// such as stock RNode. Force the portal so RTNode can claim and rewrite
|
||||
// its persisted settings explicitly.
|
||||
if (!boundary_app_marker_valid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if WiFi SSID is configured
|
||||
char ssid[33];
|
||||
for (int i = 0; i < 32; i++) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// Copyright (C) 2026, Boundary Mode Extension
|
||||
// Based on microReticulum_Firmware by Mark Qvist
|
||||
//
|
||||
// BoundaryMode.h — Configuration and runtime state for the Boundary Mode
|
||||
// firmware variant. This header defines the WiFi backbone connection
|
||||
// parameters and boundary-specific operational settings.
|
||||
// BoundaryMode.h — Configuration and runtime state for the legacy
|
||||
// "Boundary Mode" firmware variant. Going forward this should be renamed
|
||||
// "Transport Mode". It is the only intended operating mode for this fork;
|
||||
// the old multi-mode split is kept only for compatibility while the codebase
|
||||
// is being simplified.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@@ -15,8 +17,19 @@
|
||||
|
||||
#ifdef BOUNDARY_MODE
|
||||
|
||||
// Compatibility alias for the planned rename from Boundary Mode to
|
||||
// Transport Mode. New code should prefer the transport terminology even
|
||||
// while the legacy BOUNDARY_MODE compile-time flag still exists.
|
||||
#ifndef TRANSPORT_MODE
|
||||
#define TRANSPORT_MODE 1
|
||||
#endif
|
||||
|
||||
// ─── Boundary Mode Configuration ────────────────────────────────────────────
|
||||
//
|
||||
// NOTE: "Boundary Mode" is the legacy name. This should be relabeled
|
||||
// "Transport Mode" once the remaining non-transport code paths are removed.
|
||||
// In practice this is the only supported mode in this firmware branch.
|
||||
//
|
||||
// The boundary node operates with TWO RNS interfaces:
|
||||
//
|
||||
// 1. LoRaInterface (MODE_GATEWAY) — radio side, handles LoRa mesh
|
||||
@@ -72,10 +85,16 @@
|
||||
#define ADDR_CONF_IFAC_EN 0xD6 // IFAC enable flag (1 byte, 0x73 = enabled)
|
||||
#define ADDR_CONF_IFAC_NAME 0xD7 // Network name (33 bytes, null-terminated)
|
||||
#define ADDR_CONF_IFAC_PASS 0xF8 // Passphrase (33 bytes, null-terminated)
|
||||
// Total: 0x119 (281 bytes — extends beyond 256-byte CONFIG area into
|
||||
#define ADDR_CONF_APP_MARKER0 0x119 // RTNode app marker byte 0
|
||||
#define ADDR_CONF_APP_MARKER1 0x11A // RTNode app marker byte 1
|
||||
#define ADDR_CONF_APP_VERSION 0x11B // RTNode app config version
|
||||
// Total: 0x11C (284 bytes — extends beyond 256-byte CONFIG area into
|
||||
// unused EEPROM gap; safe on ESP32 where EEPROM starts at 824)
|
||||
|
||||
#define BOUNDARY_ENABLE_BYTE 0x73
|
||||
#define BOUNDARY_APP_MARKER0 0x52
|
||||
#define BOUNDARY_APP_MARKER1 0x54
|
||||
#define BOUNDARY_APP_VERSION 0x01
|
||||
|
||||
// ─── Boundary Mode Runtime State ─────────────────────────────────────────────
|
||||
#ifndef BOUNDARY_STATE_DEFINED
|
||||
@@ -115,6 +134,24 @@ extern BoundaryState boundary_state;
|
||||
|
||||
// ─── Boundary Mode EEPROM Load/Save ─────────────────────────────────────────
|
||||
|
||||
inline bool boundary_app_marker_valid() {
|
||||
return EEPROM.read(config_addr(ADDR_CONF_APP_MARKER0)) == BOUNDARY_APP_MARKER0 &&
|
||||
EEPROM.read(config_addr(ADDR_CONF_APP_MARKER1)) == BOUNDARY_APP_MARKER1;
|
||||
}
|
||||
|
||||
inline bool boundary_app_version_matches() {
|
||||
return boundary_app_marker_valid() &&
|
||||
EEPROM.read(config_addr(ADDR_CONF_APP_VERSION)) == BOUNDARY_APP_VERSION;
|
||||
}
|
||||
|
||||
inline void boundary_clear_app_marker() {
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER0), 0xFF);
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER1), 0xFF);
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_VERSION), 0xFF);
|
||||
EEPROM.write(config_addr(ADDR_CONF_BMODE), 0xFF);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
inline void boundary_load_config() {
|
||||
// Check if boundary mode is configured
|
||||
uint8_t bmode = EEPROM.read(config_addr(ADDR_CONF_BMODE));
|
||||
@@ -258,6 +295,9 @@ inline void boundary_save_config() {
|
||||
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + i), boundary_state.ifac_passphrase[i]);
|
||||
}
|
||||
EEPROM.write(config_addr(ADDR_CONF_IFAC_PASS + 32), 0x00);
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER0), BOUNDARY_APP_MARKER0);
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_MARKER1), BOUNDARY_APP_MARKER1);
|
||||
EEPROM.write(config_addr(ADDR_CONF_APP_VERSION), BOUNDARY_APP_VERSION);
|
||||
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#include "Utilities.h"
|
||||
|
||||
// CBA Boundary Mode
|
||||
// NOTE: Boundary Mode is the legacy name. This firmware branch intends to
|
||||
// converge on a single Transport Mode, with the BOUNDARY_MODE symbol kept
|
||||
// temporarily as a compatibility shim during cleanup.
|
||||
#ifdef BOUNDARY_MODE
|
||||
#include "BoundaryMode.h"
|
||||
#include "TcpInterface.h"
|
||||
@@ -525,6 +528,7 @@ void setup() {
|
||||
|
||||
// Enter config mode if: first boot with no config, OR button-triggered reboot,
|
||||
// OR bootloop detected
|
||||
bool app_marker_missing = !boundary_app_marker_valid();
|
||||
bool need_config = boundary_needs_config();
|
||||
bool config_requested = (boundary_config_request == BOUNDARY_CONFIG_MAGIC);
|
||||
bool skip_config = (boundary_skip_config == BOUNDARY_SKIP_MAGIC);
|
||||
@@ -543,6 +547,9 @@ void setup() {
|
||||
Serial.println("[Boundary] Entering config portal due to bootloop recovery");
|
||||
} else if (config_requested) {
|
||||
Serial.println("[Boundary] Config mode requested via button hold");
|
||||
} else if (app_marker_missing) {
|
||||
Serial.println("[Boundary] RTNode app marker missing — previous firmware was not RTNode or config is unclaimed");
|
||||
Serial.println("[Boundary] Starting config portal to migrate settings into RTNode");
|
||||
} else {
|
||||
Serial.println("[Boundary] No configuration found — starting config portal");
|
||||
}
|
||||
@@ -1734,6 +1741,9 @@ void serial_callback(uint8_t sbyte) {
|
||||
eeprom_conf_save();
|
||||
} else if (command == CMD_CONF_DELETE) {
|
||||
eeprom_conf_delete();
|
||||
#ifdef BOUNDARY_MODE
|
||||
boundary_clear_app_marker();
|
||||
#endif
|
||||
} else if (command == CMD_FB_EXT) {
|
||||
#if HAS_DISPLAY == true
|
||||
if (sbyte == 0xFF) {
|
||||
|
||||
BIN
Release/rnode_firmware_heltec32v3.bin
Normal file → Executable file
BIN
Release/rnode_firmware_heltec32v3.bin
Normal file → Executable file
Binary file not shown.
Binary file not shown.
8
Remote.h
8
Remote.h
@@ -78,6 +78,13 @@ void wifi_remote_start_ap() {
|
||||
void wifi_remote_start_sta() {
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
#ifdef BOUNDARY_MODE
|
||||
// Boundary mode does not expose static STA addressing in its config flow.
|
||||
// Always return the station interface to DHCP so stale legacy EEPROM data
|
||||
// cannot pin the node to an unintended address.
|
||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
#else
|
||||
|
||||
uint8_t ip[4]; bool ip_ok = true;
|
||||
for (uint8_t i = 0; i < 4; i++) { ip[i] = EEPROM.read(config_addr(ADDR_CONF_IP+i)); }
|
||||
if (ip[0]==0x00 && ip[1]==0x00 && ip[2]==0x00 && ip[3]==0x00) { ip_ok = false; }
|
||||
@@ -97,6 +104,7 @@ void wifi_remote_start_sta() {
|
||||
IPAddress dns2(1, 1, 1, 1);
|
||||
WiFi.config(sta_ip, sta_gw, sta_nm, dns1, dns2);
|
||||
}
|
||||
#endif
|
||||
|
||||
delay(100);
|
||||
if (wr_ssid[0] != 0x00) {
|
||||
|
||||
Reference in New Issue
Block a user