mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-02 06:54:18 +00:00
Stabilize T-Beam full companion startup
This commit is contained in:
+6
-5
@@ -181,11 +181,12 @@ service on ports 5001 and 5002. See the
|
||||
[full Companion guide](./companion_radio_full.md) for its build, terminal mode,
|
||||
and complete update-source workflow.
|
||||
|
||||
The LilyGo T-Beam 1W Full Companion maps a triple click of the physical button
|
||||
labeled `17` to a persistent WiFi on/off toggle. Turning WiFi off closes the
|
||||
WebConfig, Companion TCP, mOTA, and MQTT network services while USB, BLE, the
|
||||
display, GPS, and LoRa remain available. The same triple click turns WiFi back
|
||||
on even after reboot.
|
||||
The LilyGo T-Beam 1W Full Companion maps one press of the physical `BOOT` button
|
||||
(GPIO0) to a persistent WiFi on/off toggle. Turning WiFi off closes WebConfig,
|
||||
Companion TCP, mOTA, and MQTT network services while USB, BLE, the display, GPS,
|
||||
and LoRa remain available. Another BOOT press turns WiFi back on even after
|
||||
reboot. WiFi/WebConfig starts first; BLE starts two seconds later so the ESP32-S3
|
||||
can reserve the setup server's internal heap before both radios run together.
|
||||
|
||||
The companion loads runtime credentials saved in NVS. A non-placeholder
|
||||
compile-time `WIFI_SSID`/`WIFI_PWD` can be used as a first-boot fallback, but
|
||||
|
||||
@@ -80,21 +80,24 @@ clock and keeps GPS awake. Full Companion transports remain available in both
|
||||
states; WiFi modem sleep stays enabled when BLE is present because coexistence
|
||||
requires it. The selected state is retained after reboot.
|
||||
|
||||
On the LilyGo T-Beam 1W Full Companion, triple-click the physical button
|
||||
labeled `17` to turn the ESP32 WiFi radio and all WiFi services off or on. The
|
||||
screen confirms `WiFi: OFF` or `WiFi: ON`, and the selected state is retained
|
||||
after reboot. When WiFi is off, TCP ports 5000-5002, WebConfig, and MQTT are
|
||||
stopped; USB, BLE, the display, GPS, and LoRa continue to operate. Triple-click
|
||||
button 17 again to restore WiFi, including the saved station or setup-AP mode.
|
||||
On the LilyGo T-Beam 1W Full Companion, press the physical `BOOT` button once
|
||||
to turn the ESP32 WiFi radio and all WiFi services off or on. The screen confirms
|
||||
`WiFi: OFF` or `WiFi: ON`, and the selected state is retained after reboot. When
|
||||
WiFi is off, TCP ports 5000-5002, WebConfig, and MQTT are stopped; USB, BLE, the
|
||||
display, GPS, and LoRa continue to operate. Press BOOT again to restore WiFi,
|
||||
including the saved station or setup-AP mode. On boot, BLE starts two seconds
|
||||
after WiFi/WebConfig so their peak startup allocations do not overlap.
|
||||
|
||||
Artifacts are written to `out/` by default.
|
||||
|
||||
On 4 MB ESP32 boards, the full target uses a single 3 MB application
|
||||
partition so WiFi, BLE, WebConfig, and source-only mOTA fit together. Flash
|
||||
the generated `-merged.bin` when first installing this partition layout.
|
||||
Boards with 8 MB or more retain dual application partitions. Heltec V2 and
|
||||
TLora V2 use 100 contacts, 8 group channels, and a 16-frame offline queue in
|
||||
this combined profile because of internal DRAM limits.
|
||||
On 4 MB ESP32 boards, the full target uses a single 3 MB application partition
|
||||
so WiFi, BLE, WebConfig, and source-only mOTA fit together. The T-Beam 1W Full
|
||||
Companion uses that same LilyGo factory-compatible boot layout on its 16 MB
|
||||
flash because this source-only role does not install updates into a second app
|
||||
slot. Flash the generated `-merged.bin` when first installing this partition
|
||||
layout. Other boards with 8 MB or more retain dual application partitions.
|
||||
Heltec V2 and TLora V2 use 100 contacts, 8 group channels, and a 16-frame offline
|
||||
queue in this combined profile because of internal DRAM limits.
|
||||
|
||||
The nRF52 target inherits the board's ordinary USB Companion installation
|
||||
format and adds BLE plus the serial mOTA source. It does not enable an SD cache
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
#include "esp_bt.h"
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
#include <esp_heap_caps.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TBEAM_1W
|
||||
#include <esp_random.h>
|
||||
@@ -464,6 +467,20 @@ void halt() {
|
||||
static bool companion_wifi_disable_in_progress = false;
|
||||
static bool companion_wifi_services_stopped = false;
|
||||
|
||||
static void loadCompanionWiFiCredentials() {
|
||||
companion_wifi_has_credentials = WiFiSetupPortal::loadStoredCredentials(
|
||||
configured_wifi_ssid, sizeof(configured_wifi_ssid),
|
||||
configured_wifi_password, sizeof(configured_wifi_password));
|
||||
if (!companion_wifi_has_credentials
|
||||
&& !WiFiSetupPortal::isPlaceholderSSID(WIFI_SSID)) {
|
||||
strncpy(configured_wifi_ssid, WIFI_SSID, sizeof(configured_wifi_ssid) - 1);
|
||||
configured_wifi_ssid[sizeof(configured_wifi_ssid) - 1] = '\0';
|
||||
strncpy(configured_wifi_password, WIFI_PWD, sizeof(configured_wifi_password) - 1);
|
||||
configured_wifi_password[sizeof(configured_wifi_password) - 1] = '\0';
|
||||
companion_wifi_has_credentials = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isCompanionWiFiEnabled() {
|
||||
return companion_wifi_requested;
|
||||
}
|
||||
@@ -475,7 +492,7 @@ void halt() {
|
||||
if (!companion_wifi_requested && companion_wifi_active) {
|
||||
companion_wifi_disable_in_progress = true;
|
||||
}
|
||||
WIFI_DEBUG_PRINTLN("GPIO 17 triple click requested WiFi %s",
|
||||
WIFI_DEBUG_PRINTLN("BOOT/GPIO 0 click requested WiFi %s",
|
||||
companion_wifi_requested ? "on" : "off");
|
||||
return companion_wifi_requested;
|
||||
}
|
||||
@@ -651,7 +668,7 @@ void halt() {
|
||||
#endif
|
||||
companion_wifi_active = true;
|
||||
companion_wifi_services_stopped = false;
|
||||
WIFI_DEBUG_PRINTLN("WiFi enabled by GPIO 17 control");
|
||||
WIFI_DEBUG_PRINTLN("WiFi enabled by BOOT/GPIO 0 control");
|
||||
}
|
||||
|
||||
static void stopCompanionWiFiServices() {
|
||||
@@ -688,7 +705,7 @@ void halt() {
|
||||
board.setInhibitSleep(false);
|
||||
resetCompanionWiFiRecoveryState();
|
||||
companion_wifi_active = false;
|
||||
WIFI_DEBUG_PRINTLN("WiFi radio disabled by GPIO 17 control");
|
||||
WIFI_DEBUG_PRINTLN("WiFi radio disabled by BOOT/GPIO 0 control");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -706,6 +723,47 @@ void halt() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLE_PIN_CODE)
|
||||
static bool companion_bluetooth_initialized = false;
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
static uint32_t companion_bluetooth_start_at = 0;
|
||||
#endif
|
||||
|
||||
static void startCompanionBluetooth() {
|
||||
if (companion_bluetooth_initialized) return;
|
||||
|
||||
Serial.println("Companion: starting Bluetooth");
|
||||
bluetooth_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name,
|
||||
the_mesh.getBLEPin());
|
||||
if (!interface_manager.addInterface(InterfaceType::Bluetooth,
|
||||
&bluetooth_interface)) {
|
||||
Serial.println("Companion: no interface slot available for Bluetooth");
|
||||
return;
|
||||
}
|
||||
companion_bluetooth_initialized = true;
|
||||
if (interface_manager.isEnabled()) bluetooth_interface.enable();
|
||||
}
|
||||
|
||||
static void serviceDeferredCompanionBluetooth() {
|
||||
if (companion_bluetooth_initialized) return;
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
if (companion_bluetooth_start_at == 0
|
||||
|| (int32_t)(millis() - companion_bluetooth_start_at) < 0) return;
|
||||
#endif
|
||||
startCompanionBluetooth();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ESP32_PLATFORM) && defined(COMPANION_RADIO_FULL)
|
||||
static void logFullCompanionMemory(const char* stage) {
|
||||
Serial.printf(
|
||||
"Full Companion memory %s: heap=%u largest_internal=%u psram_free=%u/%u\r\n",
|
||||
stage, (unsigned)ESP.getFreeHeap(),
|
||||
(unsigned)heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL),
|
||||
(unsigned)ESP.getFreePsram(), (unsigned)ESP.getPsramSize());
|
||||
}
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
board.begin();
|
||||
@@ -827,10 +885,13 @@ void setup() {
|
||||
#error "need to define filesystem"
|
||||
#endif
|
||||
|
||||
// add bluetooth interface
|
||||
#if defined(BLE_PIN_CODE)
|
||||
bluetooth_interface.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name, the_mesh.getBLEPin());
|
||||
interface_manager.addInterface(InterfaceType::Bluetooth, &bluetooth_interface);
|
||||
// Load WiFi state before bringing up either wireless stack.
|
||||
#ifdef WIFI_SSID
|
||||
loadCompanionWiFiCredentials();
|
||||
#endif
|
||||
|
||||
#if defined(ESP32_PLATFORM) && defined(COMPANION_RADIO_FULL)
|
||||
logFullCompanionMemory("before interfaces");
|
||||
#endif
|
||||
|
||||
// add wifi interface
|
||||
@@ -846,18 +907,6 @@ void setup() {
|
||||
}
|
||||
});
|
||||
|
||||
companion_wifi_has_credentials = WiFiSetupPortal::loadStoredCredentials(
|
||||
configured_wifi_ssid, sizeof(configured_wifi_ssid),
|
||||
configured_wifi_password, sizeof(configured_wifi_password));
|
||||
if (!companion_wifi_has_credentials
|
||||
&& !WiFiSetupPortal::isPlaceholderSSID(WIFI_SSID)) {
|
||||
strncpy(configured_wifi_ssid, WIFI_SSID, sizeof(configured_wifi_ssid) - 1);
|
||||
configured_wifi_ssid[sizeof(configured_wifi_ssid) - 1] = '\0';
|
||||
strncpy(configured_wifi_password, WIFI_PWD, sizeof(configured_wifi_password) - 1);
|
||||
configured_wifi_password[sizeof(configured_wifi_password) - 1] = '\0';
|
||||
companion_wifi_has_credentials = true;
|
||||
}
|
||||
|
||||
interface_manager.addInterface(InterfaceType::WiFi, &wifi_interface);
|
||||
companion_wifi_requested = the_mesh.getNodePrefs()->wifi_enabled != 0;
|
||||
if (companion_wifi_requested) {
|
||||
@@ -866,10 +915,27 @@ void setup() {
|
||||
WiFi.setAutoReconnect(false);
|
||||
WiFi.mode(WIFI_OFF);
|
||||
board.setInhibitSleep(false);
|
||||
WIFI_DEBUG_PRINTLN("WiFi remains off from the saved GPIO 17 setting");
|
||||
WIFI_DEBUG_PRINTLN("WiFi remains off from the saved BOOT/GPIO 0 setting");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ESP32_PLATFORM) && defined(COMPANION_RADIO_FULL)
|
||||
logFullCompanionMemory("after WiFi start");
|
||||
#endif
|
||||
|
||||
// The Full ESP32 profile starts WiFi/WebConfig first, gives its AP/server two
|
||||
// seconds to settle and reserve heap, then starts BLE from loop(). Other BLE
|
||||
// companions keep their existing immediate startup.
|
||||
#if defined(BLE_PIN_CODE)
|
||||
#if defined(ESP32) && defined(COMPANION_RADIO_FULL) && defined(WIFI_SSID)
|
||||
companion_bluetooth_start_at = millis() + 2000UL;
|
||||
if (companion_bluetooth_start_at == 0) companion_bluetooth_start_at = 1;
|
||||
Serial.println("Companion: Bluetooth starts in 2 seconds");
|
||||
#else
|
||||
startCompanionBluetooth();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// add usb interface
|
||||
#if defined(ENABLE_USB_INTERFACE)
|
||||
#if defined(NRF52_PLATFORM) && defined(COMPANION_RADIO_FULL) && defined(OTA_FOLDER_SERIAL)
|
||||
@@ -1080,4 +1146,7 @@ void loop() {
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(BLE_PIN_CODE)
|
||||
serviceDeferredCompanionBluetooth();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -598,6 +598,9 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, CompanionNode
|
||||
#if defined(PIN_USER_BTN)
|
||||
user_btn.begin();
|
||||
#endif
|
||||
#if defined(TBEAM_1W) && defined(WIFI_SSID) && defined(PIN_WIFI_BTN)
|
||||
wifi_btn.begin();
|
||||
#endif
|
||||
#if defined(PIN_USER_BTN_ANA)
|
||||
analog_btn.begin();
|
||||
#endif
|
||||
@@ -628,9 +631,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, CompanionNode
|
||||
}
|
||||
|
||||
void UITask::serviceWiFiToggleButton() {
|
||||
#if defined(TBEAM_1W) && defined(WIFI_SSID) && defined(PIN_USER_BTN)
|
||||
if (user_btn.check() == BUTTON_EVENT_TRIPLE_CLICK) {
|
||||
handleTripleClick(KEY_SELECT);
|
||||
#if defined(TBEAM_1W) && defined(WIFI_SSID) && defined(PIN_WIFI_BTN)
|
||||
if (wifi_btn.check() == BUTTON_EVENT_CLICK) {
|
||||
const bool enabled = toggleCompanionWiFi();
|
||||
showAlert(enabled ? "WiFi: ON" : "WiFi: OFF", 1200);
|
||||
_next_refresh = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -812,6 +817,8 @@ bool UITask::isButtonPressed() const {
|
||||
}
|
||||
|
||||
void UITask::loop() {
|
||||
serviceWiFiToggleButton();
|
||||
|
||||
if (_interfaceManager->takePairingRequest()) {
|
||||
showPairingPin();
|
||||
}
|
||||
@@ -1013,13 +1020,7 @@ char UITask::handleDoubleClick(char c) {
|
||||
char UITask::handleTripleClick(char c) {
|
||||
MESH_DEBUG_PRINTLN("UITask: triple click triggered");
|
||||
checkDisplayOn(c);
|
||||
#if defined(TBEAM_1W) && defined(WIFI_SSID)
|
||||
const bool enabled = toggleCompanionWiFi();
|
||||
showAlert(enabled ? "WiFi: ON" : "WiFi: OFF", 1200);
|
||||
_next_refresh = 0;
|
||||
#else
|
||||
toggleBuzzer();
|
||||
#endif
|
||||
c = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,15 @@ if os.environ.get("MESHCORE_ESP32_FULL_BUILD") == "1":
|
||||
companion_radio_full = (
|
||||
os.environ.get("MESHCORE_COMPANION_RADIO_FULL") == "1"
|
||||
)
|
||||
tbeam_1w = board.get("build.variant", "") == "lilygo_tbeam_1w"
|
||||
|
||||
if flash_size >= 16 * 1024 * 1024:
|
||||
if companion_radio_full and tbeam_1w:
|
||||
# The Full Companion is an mOTA source only and never installs into a
|
||||
# second local app slot. Match LilyGo's factory T-Beam 1W boot layout so
|
||||
# a merged recovery image changes only the application, not the proven
|
||||
# boot/partition chain. The 3 MiB app slot has ample room for this role.
|
||||
partitions = "huge_app.csv"
|
||||
elif flash_size >= 16 * 1024 * 1024:
|
||||
partitions = "default_16MB.csv"
|
||||
elif flash_size >= 8 * 1024 * 1024:
|
||||
partitions = "default_8MB.csv"
|
||||
|
||||
@@ -52,6 +52,7 @@ build_flags =
|
||||
|
||||
; User interface
|
||||
-D PIN_USER_BTN=17
|
||||
-D PIN_WIFI_BTN=0
|
||||
|
||||
build_src_filter = ${esp32_base.build_src_filter}
|
||||
+<../variants/lilygo_tbeam_1w>
|
||||
|
||||
@@ -8,6 +8,12 @@ TBeam1WBoard board;
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#ifdef PIN_WIFI_BTN
|
||||
// The BOOT switch is also a normal active-low GPIO after startup. Treat it
|
||||
// as a dedicated single-click control; the board supplies a 10K pull-up,
|
||||
// and enabling the ESP32 pull-up as well keeps the input deterministic.
|
||||
MomentaryButton wifi_btn(PIN_WIFI_BTN, 0, true, true, false);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static SPIClass spi;
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
#ifdef PIN_WIFI_BTN
|
||||
extern MomentaryButton wifi_btn;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern TBeam1WBoard board;
|
||||
@@ -22,4 +25,3 @@ extern EnvironmentSensorManager sensors;
|
||||
|
||||
bool radio_init();
|
||||
mesh::LocalIdentity radio_new_identity();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user