Max: combined ble wifi initial build test

This commit is contained in:
pelgraine committed 2026-10-05 21:27:53 +11:00
1 parent 355cd594e6
commit 3fc6e73014
7 files changed
+502 -7

No files matched your search

+37
View File
@@ -73,6 +73,12 @@
#define CMD_SEND_CHANNEL_DATA 62
#define CMD_SET_DEFAULT_FLOOD_SCOPE 63 // v1.15+ (device-wide default scope name+key)
#define CMD_GET_DEFAULT_FLOOD_SCOPE 64 // v1.15+ (query current default scope)
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
#define CMD_RUN_CLI_COMMAND 66 // v14+ (upstream app command line)
// Combined BLE + WiFi companion (meck_max_ble_wifi): defined in main.cpp
extern bool meckCompanionCommand(const char* command, char* reply);
extern void meckCompanionPoll();
#endif
// Stats sub-types for CMD_GET_STATS
#define STATS_TYPE_CORE 0
@@ -108,6 +114,9 @@
#define RESP_ALLOWED_REPEAT_FREQ 26
#define RESP_CODE_CHANNEL_DATA_RECV 27
#define RESP_CODE_DEFAULT_FLOOD_SCOPE 28 // v1.15+
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
#define RESP_CODE_CLI_REPLY 29 // v14+, a reply to CMD_RUN_CLI_COMMAND
#endif
#define SEND_TIMEOUT_BASE_MILLIS 500
#define FLOOD_SEND_TIMEOUT_FACTOR 16.0f
@@ -2934,6 +2943,31 @@ void MyMesh::handleCmdFrame(size_t len) {
out_frame[i++] = RESP_CODE_AUTOADD_CONFIG;
out_frame[i++] = _prefs.autoadd_config;
_serial->writeFrame(out_frame, i);
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
} else if (cmd_frame[0] == CMD_RUN_CLI_COMMAND && len >= 3) {
// App command line (upstream MeshCore, v14+). This build answers
// upstream's wifi.* commands; anything else gets "Unknown command",
// as upstream replies to a command it does not have.
char *text = (char *)&cmd_frame[1];
text[len - 1] = 0; // ensure null
while (*text == ' ') text++; // skip leading spaces
char reply_buf[166];
char *reply = reply_buf;
reply_buf[0] = 0;
if (strlen(text) > 4 && text[2] == '|') { // optional prefix: reflect it back
memcpy(reply, text, 3);
reply += 3;
*reply = 0;
text += 3;
}
if (!meckCompanionCommand(text, reply)) {
strcat(reply_buf, "Unknown command");
}
out_frame[0] = RESP_CODE_CLI_REPLY;
int rlen = strlen(reply_buf);
memcpy(&out_frame[1], reply_buf, rlen);
_serial->writeFrame(out_frame, 1 + rlen);
#endif
} else {
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]);
@@ -4141,6 +4175,9 @@ void MyMesh::loop() {
if (_ui) _ui->setHasConnection(false);
#endif
#endif
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
meckCompanionPoll(); // app's "set wifi.enabled": switch once its reply has gone
#endif
}
bool MyMesh::advert() {
+279
View File
@@ -815,6 +815,20 @@ static uint32_t _atoi(const char* sp) {
#ifndef TCP_PORT
#define TCP_PORT 5000
#endif
#elif defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined BLE + WiFi companion (meck_max_ble_wifi test build): both
// connections built in, both off at boot, one on at a time.
#include <WiFi.h>
#include <helpers/esp32/SerialBLEInterface.h>
#undef FRAME_QUEUE_SIZE // each connection header defines its own queue size
#include <helpers/esp32/SerialWifiInterface.h>
#include "DualCompanionInterface.h"
SerialBLEInterface ble_companion;
SerialWifiInterface wifi_companion;
DualCompanionInterface serial_interface(&ble_companion, &wifi_companion);
#ifndef TCP_PORT
#define TCP_PORT 5000
#endif
#elif defined(MECK_WIFI_COMPANION)
#include <WiFi.h>
#include <helpers/esp32/SerialWifiInterface.h>
@@ -882,6 +896,235 @@ MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store
/* END GLOBAL OBJECTS */
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// ---------------------------------------------------------------------------
// Combined BLE + WiFi companion (meck_max_ble_wifi test build)
// Both connections are off at boot; turning one on turns the other off.
// Free memory is logged on serial ("MEM ...") at boot, after each switch and
// when the Web Reader starts, for the feasibility measurements.
// ---------------------------------------------------------------------------
static bool meckBtReleased = false; // Web Reader has freed Bluetooth's memory
static bool meckWifiServerStarted = false; // app server (TCP_PORT) started once
static int8_t meckPendingWifi = -1; // app's "set wifi.enabled": -1 none, 0 off, 1 on
static unsigned long meckPendingWifiAt = 0;
static void meckLogMemory(const char* when) {
Serial.printf("MEM %s: heap free=%u largest=%u, PSRAM free=%u\n", when,
(unsigned)ESP.getFreeHeap(), (unsigned)ESP.getMaxAllocHeap(),
(unsigned)ESP.getFreePsram());
}
bool meckCompanionIsBLE() {
return serial_interface.getMode() == DualCompanionInterface::MODE_BLE;
}
bool meckCompanionIsWiFi() {
return serial_interface.getMode() == DualCompanionInterface::MODE_WIFI;
}
// Read /web/wifi.cfg (line 1 network name, line 2 password), as Settings
// writes it. Values are cut to upstream's sizes (32 and 63 characters).
static bool meckWifiCfgRead(char* ssid, size_t ssidLen, char* pass, size_t passLen) {
ssid[0] = 0;
pass[0] = 0;
if (!sdCardReady) return false;
if (!SD.exists("/web/wifi.cfg")) {
digitalWrite(SDCARD_CS, HIGH);
return false;
}
File f = SD.open("/web/wifi.cfg", FILE_READ);
if (!f) {
digitalWrite(SDCARD_CS, HIGH);
return false;
}
String s = f.readStringUntil('\n'); s.trim();
String p = f.readStringUntil('\n'); p.trim();
f.close();
digitalWrite(SDCARD_CS, HIGH);
snprintf(ssid, ssidLen, "%s", s.c_str());
snprintf(pass, passLen, "%s", p.c_str());
return true;
}
// Write /web/wifi.cfg the same way the Settings WiFi setup does.
static bool meckWifiCfgWrite(const char* ssid, const char* pass) {
if (!sdCardReady) return false;
bool ok = false;
if (SD.exists("/web") || SD.mkdir("/web")) {
File f = SD.open("/web/wifi.cfg", FILE_WRITE);
if (f) {
f.println(ssid);
f.println(pass);
f.close();
ok = true;
}
}
digitalWrite(SDCARD_CS, HIGH);
return ok;
}
static void meckWifiOff() {
wifi_companion.disable();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
}
void meckCompanionUseNone() {
if (meckCompanionIsBLE()) ble_companion.disable();
if (meckCompanionIsWiFi()) meckWifiOff();
serial_interface.setMode(DualCompanionInterface::MODE_NONE);
Serial.println("Companion: Bluetooth and WiFi off");
meckLogMemory("both off");
}
// Bluetooth on, WiFi off. Fails once the Web Reader has freed Bluetooth's
// memory: as in the BLE build, Bluetooth then needs a reboot.
bool meckCompanionUseBLE() {
if (meckCompanionIsBLE()) return true;
if (meckBtReleased) {
Serial.println("Companion: Bluetooth unavailable until reboot (freed for the Web Reader)");
return false;
}
if (meckCompanionIsWiFi()) meckWifiOff();
serial_interface.setMode(DualCompanionInterface::MODE_BLE);
ble_companion.enable();
Serial.println("Companion: Bluetooth on");
meckLogMemory("Bluetooth on");
return true;
}
// WiFi on, Bluetooth off. connectSaved joins the network in /web/wifi.cfg,
// waiting up to 8 s as the Settings WiFi toggle does; WiFi setup passes
// false because it scans and joins by itself.
bool meckCompanionUseWiFi(bool connectSaved) {
if (meckCompanionIsWiFi()) return true;
if (meckCompanionIsBLE()) ble_companion.disable();
serial_interface.setMode(DualCompanionInterface::MODE_NONE);
meckLogMemory("before WiFi on");
if (!WiFi.mode(WIFI_STA)) {
Serial.println("Companion: WiFi STA init FAILED");
WiFi.mode(WIFI_OFF);
meckLogMemory("WiFi init failed");
return false;
}
if (!meckWifiServerStarted) {
wifi_companion.begin(TCP_PORT);
meckWifiServerStarted = true;
}
serial_interface.setMode(DualCompanionInterface::MODE_WIFI);
wifi_companion.enable();
if (connectSaved) {
char ssid[33], pass[64];
if (meckWifiCfgRead(ssid, sizeof(ssid), pass, sizeof(pass)) && ssid[0]) {
WiFi.begin(ssid, pass);
unsigned long timeout = millis() + 8000;
while (WiFi.status() != WL_CONNECTED && millis() < timeout) {
delay(100);
}
if (WiFi.status() == WL_CONNECTED) {
Serial.printf("Companion: WiFi on, connected to %s, IP: %s\n",
ssid, WiFi.localIP().toString().c_str());
} else {
Serial.println("Companion: WiFi on, but connection failed");
}
} else {
Serial.println("Companion: WiFi on, no saved network (set one in Settings)");
}
} else {
Serial.println("Companion: WiFi on");
}
meckLogMemory("WiFi on");
return true;
}
// App command line (message 66): upstream MeshCore's wifi.* commands, with
// the network kept in /web/wifi.cfg as Settings keeps it. Replies are worded
// as upstream's. Returns false for any other command (the caller then
// replies "Unknown command", as upstream does).
bool meckCompanionCommand(const char* command, char* reply) {
char ssid[33], pass[64]; // upstream's wifi_ssid / wifi_pwd sizes
if (memcmp(command, "set wifi.ssid ", 14) == 0) {
meckWifiCfgRead(ssid, sizeof(ssid), pass, sizeof(pass));
snprintf(ssid, sizeof(ssid), "%s", &command[14]);
if (!meckWifiCfgWrite(ssid, pass)) {
strcpy(reply, "Error, can't save to SD card");
return true;
}
sprintf(reply, "> wifi.ssid is now %s (set wifi.pwd too, then reboot)", ssid);
return true;
}
if (memcmp(command, "set wifi.pwd ", 13) == 0) {
meckWifiCfgRead(ssid, sizeof(ssid), pass, sizeof(pass));
snprintf(pass, sizeof(pass), "%s", &command[13]);
if (!meckWifiCfgWrite(ssid, pass)) {
strcpy(reply, "Error, can't save to SD card");
return true;
}
strcpy(reply, "> wifi.pwd updated (reboot to apply)");
return true;
}
if (strcmp(command, "get wifi.pwd") == 0) {
meckWifiCfgRead(ssid, sizeof(ssid), pass, sizeof(pass));
sprintf(reply, "> %s", pass);
return true;
}
if (strcmp(command, "set wifi.clear") == 0) {
if (!meckWifiCfgWrite("", "")) {
strcpy(reply, "Error, can't save to SD card");
return true;
}
strcpy(reply, "> wifi config cleared (reboot to apply)");
return true;
}
if (strcmp(command, "get wifi.ssid") == 0) {
meckWifiCfgRead(ssid, sizeof(ssid), pass, sizeof(pass));
sprintf(reply, "> %s", ssid[0] ? ssid : "(not set)");
return true;
}
if (memcmp(command, "set wifi.enabled ", 17) == 0) {
int en = atoi(&command[17]) ? 1 : 0;
// Both are off at boot in this build, so this switches WiFi now: one
// second after the reply, so the reply still reaches the app. WiFi on
// turns Bluetooth off.
meckPendingWifi = en;
meckPendingWifiAt = millis() + 1000;
sprintf(reply, "> wifi.enabled is now %d (reboot to apply)", en);
return true;
}
if (strcmp(command, "get wifi.enabled") == 0) {
sprintf(reply, "> %d", meckCompanionIsWiFi() ? 1 : 0);
return true;
}
if (strcmp(command, "get wifi.status") == 0) {
strcpy(reply, WiFi.status() == WL_CONNECTED ? "> connected" : "> disconnected");
return true;
}
if (strcmp(command, "get wifi.ip") == 0) {
if (WiFi.status() == WL_CONNECTED) {
sprintf(reply, "> %s", WiFi.localIP().toString().c_str());
} else {
strcpy(reply, "> (not connected)");
}
return true;
}
return false;
}
// Called from MyMesh::loop(): runs the app's "set wifi.enabled" switch once
// its reply has had time to go out.
void meckCompanionPoll() {
if (meckPendingWifi < 0) return;
if ((long)(millis() - meckPendingWifiAt) < 0) return;
int8_t want = meckPendingWifi;
meckPendingWifi = -1;
if (want == 1 && !meckCompanionIsWiFi()) {
meckCompanionUseWiFi(true);
} else if (want == 0 && meckCompanionIsWiFi()) {
meckCompanionUseNone();
}
}
#endif
// ---------------------------------------------------------------------------
// Voice-over-LoRa: incoming raw packet handler (dz0ny VE3 protocol)
// Registered with the_mesh.setVoiceHandler() when voice screen is created.
@@ -2039,6 +2282,12 @@ void setup() {
MESH_DEBUG_PRINTLN("setup() - WiFi mode (compile-time credentials)");
WiFi.begin(WIFI_SSID, WIFI_PWD);
serial_interface.begin(TCP_PORT);
#elif defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined BLE + WiFi companion: both off at boot. Bluetooth is only
// prepared here (its controller starts on first use); WiFi and the app
// server start when the user turns WiFi on.
MESH_DEBUG_PRINTLN("setup() - combined BLE + WiFi companion, both off at boot");
ble_companion.begin(BLE_NAME_PREFIX, the_mesh.getNodePrefs()->node_name, the_mesh.getBLEPin());
#elif defined(MECK_WIFI_COMPANION)
{
// WiFi companion: load credentials from SD at runtime.
@@ -2366,6 +2615,9 @@ void setup() {
#ifdef ESP32
Serial.printf("setup() complete - free heap: %d, largest block: %d\n",
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
#endif
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
meckLogMemory("boot, both off");
#endif
{
void* p25 = malloc(25000); void* p10 = malloc(10000); void* p4 = malloc(4000);
@@ -4554,6 +4806,32 @@ void handleKeyboardInput() {
Serial.println("Opening web reader");
{
static bool webReaderWifiReady = false;
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined build: with the WiFi companion on, WiFi is already up and
// Bluetooth is off, so nothing needs freeing. Otherwise do as the BLE
// build does, once per boot: switch the Bluetooth companion off, free
// Bluetooth's memory (it then needs a reboot) and start WiFi.
if (!meckCompanionIsWiFi() && !webReaderWifiReady) {
if (meckCompanionIsBLE()) meckCompanionUseNone();
Serial.printf("WebReader: heap BEFORE BT release: free=%d, largest=%d\n",
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
btStop();
delay(50);
esp_bt_controller_mem_release(ESP_BT_MODE_BTDM);
delay(50);
meckBtReleased = true;
Serial.printf("WebReader: heap AFTER BT release: free=%d, largest=%d\n",
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
if (WiFi.mode(WIFI_STA)) {
Serial.println("WebReader: WiFi STA init OK");
webReaderWifiReady = true;
} else {
Serial.println("WebReader: WiFi STA init FAILED");
WiFi.mode(WIFI_OFF);
}
}
meckLogMemory("Web Reader start");
#else
#ifdef MECK_WIFI_COMPANION
// WiFi companion: WiFi is already up from boot, no BLE to tear down
webReaderWifiReady = true;
@@ -4592,6 +4870,7 @@ void handleKeyboardInput() {
Serial.printf("WebReader: heap after WiFi init: free=%d, largest=%d\n",
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
}
#endif
}
ui_task.gotoWebReader();
break;
@@ -0,0 +1,48 @@
#pragma once
// Combined BLE + WiFi companion (meck_max_ble_wifi test build).
//
// Holds the Bluetooth and the WiFi companion connections and passes every
// call to whichever one is selected. Only one is selected at a time; with
// neither selected it behaves as a switched-off connection. Selecting a
// connection and switching the radios on and off is done in main.cpp
// (meckCompanionUseBLE / meckCompanionUseWiFi / meckCompanionUseNone).
#include <helpers/BaseSerialInterface.h>
class DualCompanionInterface : public BaseSerialInterface {
public:
enum Mode : uint8_t { MODE_NONE = 0, MODE_BLE = 1, MODE_WIFI = 2 };
private:
BaseSerialInterface* _ble;
BaseSerialInterface* _wifi;
Mode _mode;
BaseSerialInterface* active() const {
if (_mode == MODE_BLE) return _ble;
if (_mode == MODE_WIFI) return _wifi;
return nullptr;
}
public:
DualCompanionInterface(BaseSerialInterface* ble, BaseSerialInterface* wifi)
: _ble(ble), _wifi(wifi), _mode(MODE_NONE) { }
Mode getMode() const { return _mode; }
void setMode(Mode m) { _mode = m; }
// BaseSerialInterface methods, passed to the selected connection
void enable() override { if (active()) active()->enable(); }
void disable() override { if (active()) active()->disable(); }
bool isEnabled() const override { return active() ? active()->isEnabled() : false; }
bool isConnected() const override { return active() ? active()->isConnected() : false; }
bool isWriteBusy() const override { return active() ? active()->isWriteBusy() : false; }
bool hasPendingData() const override { return active() ? active()->hasPendingData() : false; }
size_t writeFrame(const uint8_t src[], size_t len) override {
return active() ? active()->writeFrame(src, len) : 0;
}
size_t checkRecvFrame(uint8_t dest[]) override {
return active() ? active()->checkRecvFrame(dest) : 0;
}
};
@@ -1048,7 +1048,16 @@ public:
extern void otaResumeRadio();
otaResumeRadio();
// Try to restore STA WiFi from saved credentials
#ifdef MECK_WIFI_COMPANION
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
{
// Combined build: only if WiFi was the companion connection
extern bool meckCompanionIsWiFi();
if (meckCompanionIsWiFi()) {
WiFi.mode(WIFI_STA);
wifiReconnectSaved();
}
}
#elif defined(MECK_WIFI_COMPANION)
WiFi.mode(WIFI_STA);
wifiReconnectSaved();
#endif
@@ -1474,7 +1483,16 @@ public:
_editMode = EDIT_NONE;
extern void otaResumeRadio();
otaResumeRadio();
#ifdef MECK_WIFI_COMPANION
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
{
// Combined build: only if WiFi was the companion connection
extern bool meckCompanionIsWiFi();
if (meckCompanionIsWiFi()) {
WiFi.mode(WIFI_STA);
wifiReconnectSaved();
}
}
#elif defined(MECK_WIFI_COMPANION)
WiFi.mode(WIFI_STA);
wifiReconnectSaved();
#endif
@@ -3529,11 +3547,33 @@ public:
#ifdef MECK_WIFI_COMPANION
case ROW_WIFI_SETUP: {
// Launch WiFi scan → select → password → connect flow
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
{
// Combined build: WiFi setup makes WiFi the companion connection
// (Bluetooth goes off), as one connection is on at a time
extern bool meckCompanionUseWiFi(bool connectSaved);
meckCompanionUseWiFi(false);
}
#endif
_editMode = EDIT_WIFI;
performWifiScan();
break;
}
case ROW_WIFI_TOGGLE:
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
{
// Combined build: WiFi on turns Bluetooth off; WiFi off leaves
// neither on
extern bool meckCompanionIsWiFi();
extern bool meckCompanionUseWiFi(bool connectSaved);
extern void meckCompanionUseNone();
if (meckCompanionIsWiFi()) {
meckCompanionUseNone();
} else {
meckCompanionUseWiFi(true);
}
}
#else
if (WiFi.getMode() != WIFI_OFF) {
// Turn WiFi OFF
WiFi.disconnect(true);
@@ -3567,6 +3607,7 @@ public:
}
Serial.println("Settings: WiFi radio ON");
}
#endif
break;
#endif
#ifdef HAS_4G_MODEM
+50 -4
View File
@@ -30,6 +30,12 @@
#if defined(WIFI_SSID) || defined(MECK_WIFI_COMPANION)
#include <WiFi.h>
#endif
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined BLE + WiFi companion (meck_max_ble_wifi): defined in main.cpp
extern bool meckCompanionIsBLE();
extern bool meckCompanionUseBLE();
extern void meckCompanionUseNone();
#endif
#ifndef AUTO_OFF_MILLIS
#define AUTO_OFF_MILLIS 15000 // 15 seconds
@@ -147,7 +153,8 @@ class HomeScreen : public UIScreen {
RADIO,
#ifdef BLE_PIN_CODE
BLUETOOTH,
#elif defined(MECK_WIFI_COMPANION)
#endif
#ifdef MECK_WIFI_COMPANION
WIFI_STATUS,
#endif
ADVERT,
@@ -697,7 +704,12 @@ public:
}
}
#endif
#ifdef BLE_PIN_CODE
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined build: show the PIN only while Bluetooth is the connection
if (rightBuf[0] == 0 && meckCompanionIsBLE() && _task->isSerialEnabled() && the_mesh.getBLEPin() != 0) {
sprintf(rightBuf, "Pin:%d", the_mesh.getBLEPin());
}
#elif defined(BLE_PIN_CODE)
if (rightBuf[0] == 0 && _task->isSerialEnabled() && the_mesh.getBLEPin() != 0) {
sprintf(rightBuf, "Pin:%d", the_mesh.getBLEPin());
}
@@ -946,7 +958,30 @@ public:
display.setCursor(0, 64);
sprintf(tmp, "RX packets: %u", (unsigned)the_mesh.getRxPacketCount());
display.print(tmp);
#ifdef BLE_PIN_CODE
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
} else if (_page == HomePage::BLUETOOTH) {
// Combined build: Bluetooth counts as on only while it is the
// connection, not while WiFi is
bool btOn = meckCompanionIsBLE() && _task->isSerialEnabled();
display.setColor(DisplayDriver::GREEN);
display.drawXbm((display.width() - 32) / 2, 18,
btOn ? bluetooth_on : bluetooth_off,
32, 32);
if (btOn && _task->hasConnection()) {
display.setColor(DisplayDriver::GREEN);
display.setTextSize(1);
display.drawTextCentered(display.width() / 2, 53, "< Connected >");
} else if (btOn && the_mesh.getBLEPin() != 0) {
display.setColor(DisplayDriver::RED);
display.setTextSize(2);
sprintf(tmp, "Pin:%d", the_mesh.getBLEPin());
display.drawTextCentered(display.width() / 2, 53, tmp);
}
display.setColor(DisplayDriver::GREEN);
display.setTextSize(1);
display.drawTextCentered(display.width() / 2, 68, "toggle: " PRESS_LABEL);
display.drawTextCentered(display.width() / 2, 78, "or press Enter key");
#elif defined(BLE_PIN_CODE)
} else if (_page == HomePage::BLUETOOTH) {
display.setColor(DisplayDriver::GREEN);
display.drawXbm((display.width() - 32) / 2, 18,
@@ -1356,7 +1391,18 @@ public:
}
return true;
}
#ifdef BLE_PIN_CODE
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
if (c == KEY_ENTER && _page == HomePage::BLUETOOTH) {
// Combined build: Bluetooth on turns WiFi off; Bluetooth off leaves
// neither on. Once the Web Reader has freed Bluetooth, it needs a reboot.
if (meckCompanionIsBLE()) {
meckCompanionUseNone();
} else if (!meckCompanionUseBLE()) {
_task->showAlert("Reboot for Bluetooth", 1500);
}
return true;
}
#elif defined(BLE_PIN_CODE)
if (c == KEY_ENTER && _page == HomePage::BLUETOOTH) {
if (_task->isSerialEnabled()) { // toggle Bluetooth on/off
_task->disableSerial();
@@ -5141,7 +5141,17 @@ public:
if (_tlsClient) { delete _tlsClient; _tlsClient = nullptr; }
_tlsHost = String();
#ifdef MECK_WIFI_COMPANION
#if defined(BLE_PIN_CODE) && defined(MECK_WIFI_COMPANION)
// Combined build: keep WiFi up only if it is the companion connection
extern bool meckCompanionIsWiFi();
if (meckCompanionIsWiFi()) {
_wifiState = WIFI_CONNECTED; // WiFi is still up
} else {
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
_wifiState = WIFI_IDLE;
}
#elif defined(MECK_WIFI_COMPANION)
// WiFi companion: keep WiFi alive for the companion TCP server.
// Don't disconnect or change mode — just reset our internal state.
_wifiState = WIFI_CONNECTED; // WiFi is still up
+34
View File
@@ -295,6 +295,40 @@ lib_deps =
bitbank2/JPEGDEC
bitbank2/PNGdec
; MAX combined BLE + WiFi companion: TEST BUILD. Both connections built in,
; both off at boot; turning one on turns the other off. Answers the app's
; command-line message (66) for upstream's wifi.* commands. Free memory is
; logged on serial ("MEM ...") at boot, after each switch and when the Web
; Reader starts. Flags are meck_max_ble's plus meck_max_wifi's.
[env:meck_max_ble_wifi]
extends = LilyGo_TDeck_Pro_Max
build_flags =
${LilyGo_TDeck_Pro_Max.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=2000
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D MECK_BLE_TX_POWER=ESP_PWR_LVL_P15
-D MECK_WIFI_COMPANION=1
-D TCP_PORT=5000
-D WIFI_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D MECK_WEB_READER=1
-D MECK_OTA_UPDATE=1
-D HAS_4G_MODEM=1
-D FIRMWARE_VERSION='"Meck v1.14.MAX.BLE-WiFi"'
build_src_filter = ${LilyGo_TDeck_Pro_Max.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
+<helpers/ui/GxEPDDisplay.cpp>
lib_deps =
${LilyGo_TDeck_Pro_Max.lib_deps}
densaugeo/base64 @ ~1.4.0
bitbank2/JPEGDEC
bitbank2/PNGdec
; MAX standalone (no BLE/WiFi — maximum battery life, LoRa mesh only)
; Contacts in PSRAM (2000 capacity). OTA enabled (WiFi AP on demand).
[env:meck_max_standalone]