feat(companion-wifi): recovery AP with TCP rescue CLI when WiFi is down
When a companion WiFi device has no WiFi credentials or can't connect for 60s, it broadcasts an 'EastMesh-WiFi' AP (WPA2 password = device pin zero-padded to 8 digits; open if no pin set) with the rescue CLI on TCP port 23, so wifi.ssid/pwd can be fixed without a serial cable. - rescue CLI command handler now writes to any Stream (Serial or the TCP rescue client) - while the AP is up, STA keeps retrying; the AP shuts down automatically once the configured network connects - 'set wifi.ssid/pwd' keeps AP+STA mode during a rescue session so the session isn't dropped mid-config - guard ESP32-only SD/SPI code in ArchiveStorage so non-ESP32 builds of the shared helpers get further Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c6698c5bad
commit
a5c9ba3e01
@@ -260,3 +260,20 @@ Companion Wi-Fi builds also still support the existing rescue commands such as:
|
||||
- `cat ...`
|
||||
- `rm ...`
|
||||
- `reboot`
|
||||
|
||||
### Recovery Access Point
|
||||
|
||||
When a companion Wi-Fi device has no Wi-Fi credentials configured, or cannot connect
|
||||
to its configured network for 60 seconds, it broadcasts its own `EastMesh-WiFi`
|
||||
access point so it can be rescued without a serial cable:
|
||||
|
||||
- the AP password is the device's 6-digit pin (`set pin ...`) zero-padded to 8 digits,
|
||||
e.g. pin `123456` gives Wi-Fi password `00123456`
|
||||
- if no pin has been set, the AP is **open** — set a pin first if the device is in a
|
||||
public area
|
||||
- connect to the AP, then open the rescue CLI with `telnet 192.168.4.1` (or
|
||||
`nc 192.168.4.1 23`); all rescue commands above are available
|
||||
- typical recovery: `set wifi.ssid <ssid>`, `set wifi.pwd <password>`, `reboot`
|
||||
- while the AP is up the device keeps retrying its configured network; as soon as the
|
||||
station connection succeeds the recovery AP shuts down automatically
|
||||
- the MeshCore app can also reach the device through the AP on the usual TCP port
|
||||
|
||||
@@ -2103,48 +2103,44 @@ void MyMesh::enterCLIRescue() {
|
||||
Serial.println("========= CLI Rescue =========");
|
||||
}
|
||||
|
||||
void MyMesh::checkCLIRescueCmd() {
|
||||
int len = strlen(cli_command);
|
||||
while (Serial.available() && len < sizeof(cli_command)-1) {
|
||||
char c = Serial.read();
|
||||
if (c != '\n') {
|
||||
cli_command[len++] = c;
|
||||
cli_command[len] = 0;
|
||||
}
|
||||
Serial.print(c); // echo
|
||||
}
|
||||
if (len == sizeof(cli_command)-1) { // command buffer full
|
||||
cli_command[sizeof(cli_command)-1] = '\r';
|
||||
}
|
||||
#if defined(ESP32)
|
||||
void MyMesh::applyStationMode() {
|
||||
#if defined(WIFI_SSID)
|
||||
// keep the recovery AP up (AP+STA) so a rescue session isn't dropped mid-config
|
||||
WiFi.mode(_recovery_ap_active ? WIFI_AP_STA : WIFI_STA);
|
||||
#else
|
||||
WiFi.mode(WIFI_STA);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len > 0 && cli_command[len - 1] == '\r') { // received complete line
|
||||
cli_command[len - 1] = 0; // replace newline with C string null terminator
|
||||
void MyMesh::handleRescueCommand(char* command, Stream& out) {
|
||||
|
||||
if (memcmp(cli_command, "set ", 4) == 0) {
|
||||
const char* config = &cli_command[4];
|
||||
if (memcmp(command, "set ", 4) == 0) {
|
||||
const char* config = &command[4];
|
||||
if (memcmp(config, "pin ", 4) == 0) {
|
||||
_prefs.ble_pin = atoi(&config[4]);
|
||||
savePrefs();
|
||||
Serial.printf(" > pin is now %06d\n", _prefs.ble_pin);
|
||||
out.printf(" > pin is now %06d\n", _prefs.ble_pin);
|
||||
#if defined(ESP32)
|
||||
} else if (memcmp(config, "wifi.ssid ", 10) == 0) {
|
||||
StrHelper::strncpy(_prefs.wifi_ssid, &config[10], sizeof(_prefs.wifi_ssid));
|
||||
savePrefs();
|
||||
if (_prefs.wifi_ssid[0]) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
applyStationMode();
|
||||
WiFi.setSleep(toEspPowerSave(_prefs.wifi_powersave));
|
||||
WiFi.begin(_prefs.wifi_ssid, _prefs.wifi_pwd);
|
||||
}
|
||||
Serial.printf(" > wifi.ssid is now: %s\n", _prefs.wifi_ssid[0] ? _prefs.wifi_ssid : "-");
|
||||
out.printf(" > wifi.ssid is now: %s\n", _prefs.wifi_ssid[0] ? _prefs.wifi_ssid : "-");
|
||||
} else if (memcmp(config, "wifi.pwd ", 9) == 0) {
|
||||
StrHelper::strncpy(_prefs.wifi_pwd, &config[9], sizeof(_prefs.wifi_pwd));
|
||||
savePrefs();
|
||||
if (_prefs.wifi_ssid[0]) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
applyStationMode();
|
||||
WiFi.setSleep(toEspPowerSave(_prefs.wifi_powersave));
|
||||
WiFi.begin(_prefs.wifi_ssid, _prefs.wifi_pwd);
|
||||
}
|
||||
Serial.println(" > wifi.pwd updated");
|
||||
out.println(" > wifi.pwd updated");
|
||||
} else if (memcmp(config, "wifi.powersaving ", 17) == 0) {
|
||||
uint8_t next_mode = 0xFF;
|
||||
if (strcmp(&config[17], "none") == 0) {
|
||||
@@ -2158,67 +2154,67 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
_prefs.wifi_powersave = next_mode;
|
||||
savePrefs();
|
||||
WiFi.setSleep(toEspPowerSave(_prefs.wifi_powersave));
|
||||
Serial.printf(" > wifi.powersaving is now: %s\n", getPowerSaveLabel(_prefs.wifi_powersave));
|
||||
out.printf(" > wifi.powersaving is now: %s\n", getPowerSaveLabel(_prefs.wifi_powersave));
|
||||
} else {
|
||||
Serial.println(" Error: bad wifi.powersaving");
|
||||
out.println(" Error: bad wifi.powersaving");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
Serial.printf(" Error: unknown config: %s\n", config);
|
||||
out.printf(" Error: unknown config: %s\n", config);
|
||||
}
|
||||
} else if (strcmp(cli_command, "get wifi.ssid") == 0) {
|
||||
} else if (strcmp(command, "get wifi.ssid") == 0) {
|
||||
#if defined(ESP32)
|
||||
Serial.printf(" > %s\n", _prefs.wifi_ssid[0] ? _prefs.wifi_ssid : "-");
|
||||
out.printf(" > %s\n", _prefs.wifi_ssid[0] ? _prefs.wifi_ssid : "-");
|
||||
#else
|
||||
Serial.println(" Error: wifi unsupported");
|
||||
out.println(" Error: wifi unsupported");
|
||||
#endif
|
||||
} else if (strcmp(cli_command, "get wifi.powersaving") == 0) {
|
||||
} else if (strcmp(command, "get wifi.powersaving") == 0) {
|
||||
#if defined(ESP32)
|
||||
Serial.printf(" > %s\n", getPowerSaveLabel(_prefs.wifi_powersave));
|
||||
out.printf(" > %s\n", getPowerSaveLabel(_prefs.wifi_powersave));
|
||||
#else
|
||||
Serial.println(" Error: wifi unsupported");
|
||||
out.println(" Error: wifi unsupported");
|
||||
#endif
|
||||
} else if (strcmp(cli_command, "get wifi.status") == 0) {
|
||||
} else if (strcmp(command, "get wifi.status") == 0) {
|
||||
#if defined(ESP32)
|
||||
wl_status_t status = WiFi.status();
|
||||
if (_prefs.wifi_ssid[0] == 0) {
|
||||
Serial.println(" > ssid:- status:off code:255 state:unconfigured");
|
||||
out.println(" > ssid:- status:off code:255 state:unconfigured");
|
||||
} else if (status == WL_CONNECTED) {
|
||||
const int rssi_dbm = WiFi.RSSI();
|
||||
Serial.printf(" > ssid:%s status:connected code:%d state:%s ip:%s rssi:%d quality:%d%% signal:%s\n",
|
||||
out.printf(" > ssid:%s status:connected code:%d state:%s ip:%s rssi:%d quality:%d%% signal:%s\n",
|
||||
_prefs.wifi_ssid, static_cast<int>(status), getWifiStateLabel(status),
|
||||
WiFi.localIP().toString().c_str(), rssi_dbm, getWifiQualityPercent(rssi_dbm),
|
||||
getWifiQualityLabel(rssi_dbm));
|
||||
} else {
|
||||
const char* overall = (status == WL_IDLE_STATUS) ? "connecting" : "disconnected";
|
||||
Serial.printf(" > ssid:%s status:%s code:%d state:%s\n", _prefs.wifi_ssid, overall,
|
||||
out.printf(" > ssid:%s status:%s code:%d state:%s\n", _prefs.wifi_ssid, overall,
|
||||
static_cast<int>(status), getWifiStateLabel(status));
|
||||
}
|
||||
#else
|
||||
Serial.println(" Error: wifi unsupported");
|
||||
out.println(" Error: wifi unsupported");
|
||||
#endif
|
||||
} else if (strcmp(cli_command, "rebuild") == 0) {
|
||||
} else if (strcmp(command, "rebuild") == 0) {
|
||||
bool success = _store->formatFileSystem();
|
||||
if (success) {
|
||||
_store->saveMainIdentity(self_id);
|
||||
savePrefs();
|
||||
saveContacts();
|
||||
saveChannels();
|
||||
Serial.println(" > erase and rebuild done");
|
||||
out.println(" > erase and rebuild done");
|
||||
} else {
|
||||
Serial.println(" Error: erase failed");
|
||||
out.println(" Error: erase failed");
|
||||
}
|
||||
} else if (strcmp(cli_command, "erase") == 0) {
|
||||
} else if (strcmp(command, "erase") == 0) {
|
||||
bool success = _store->formatFileSystem();
|
||||
if (success) {
|
||||
Serial.println(" > erase done");
|
||||
out.println(" > erase done");
|
||||
} else {
|
||||
Serial.println(" Error: erase failed");
|
||||
out.println(" Error: erase failed");
|
||||
}
|
||||
} else if (memcmp(cli_command, "ls", 2) == 0) {
|
||||
} else if (memcmp(command, "ls", 2) == 0) {
|
||||
|
||||
// get path from command e.g: "ls /adafruit"
|
||||
const char *path = &cli_command[3];
|
||||
const char *path = &command[3];
|
||||
|
||||
bool is_fs2 = false;
|
||||
if (memcmp(path, "UserData/", 9) == 0) {
|
||||
@@ -2227,7 +2223,7 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
path += 7; // skip "ExtraFS"
|
||||
is_fs2 = true;
|
||||
}
|
||||
Serial.printf("Listing files in %s\n", path);
|
||||
out.printf("Listing files in %s\n", path);
|
||||
|
||||
// log each file and directory
|
||||
File root = _store->openRead(path);
|
||||
@@ -2236,9 +2232,9 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
if (file.isDirectory()) {
|
||||
Serial.printf("[dir] UserData%s/%s\n", path, file.name());
|
||||
out.printf("[dir] UserData%s/%s\n", path, file.name());
|
||||
} else {
|
||||
Serial.printf("[file] UserData%s/%s (%d bytes)\n", path, file.name(), file.size());
|
||||
out.printf("[file] UserData%s/%s (%d bytes)\n", path, file.name(), file.size());
|
||||
}
|
||||
// move to next file
|
||||
file = root.openNextFile();
|
||||
@@ -2253,9 +2249,9 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
File file = root2.openNextFile();
|
||||
while (file) {
|
||||
if (file.isDirectory()) {
|
||||
Serial.printf("[dir] ExtraFS%s/%s\n", path, file.name());
|
||||
out.printf("[dir] ExtraFS%s/%s\n", path, file.name());
|
||||
} else {
|
||||
Serial.printf("[file] ExtraFS%s/%s (%d bytes)\n", path, file.name(), file.size());
|
||||
out.printf("[file] ExtraFS%s/%s (%d bytes)\n", path, file.name(), file.size());
|
||||
}
|
||||
// move to next file
|
||||
file = root2.openNextFile();
|
||||
@@ -2263,10 +2259,10 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
root2.close();
|
||||
}
|
||||
}
|
||||
} else if (memcmp(cli_command, "cat", 3) == 0) {
|
||||
} else if (memcmp(command, "cat", 3) == 0) {
|
||||
|
||||
// get path from command e.g: "cat /contacts3"
|
||||
const char *path = &cli_command[4];
|
||||
const char *path = &command[4];
|
||||
|
||||
bool is_fs2 = false;
|
||||
if (memcmp(path, "UserData/", 9) == 0) {
|
||||
@@ -2275,8 +2271,7 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
path += 7; // skip "ExtraFS"
|
||||
is_fs2 = true;
|
||||
} else {
|
||||
Serial.println("Invalid path provided, must start with UserData/ or ExtraFS/");
|
||||
cli_command[0] = 0;
|
||||
out.println("Invalid path provided, must start with UserData/ or ExtraFS/");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2294,19 +2289,19 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
|
||||
// print hex
|
||||
mesh::Utils::printHex(Serial, buffer, file_size);
|
||||
Serial.print("\n");
|
||||
out.print("\n");
|
||||
|
||||
file.close();
|
||||
|
||||
}
|
||||
|
||||
} else if (memcmp(cli_command, "rm ", 3) == 0) {
|
||||
} else if (memcmp(command, "rm ", 3) == 0) {
|
||||
// get path from command e.g: "rm /adv_blobs"
|
||||
const char *path = &cli_command[3];
|
||||
const char *path = &command[3];
|
||||
MESH_DEBUG_PRINTLN("Removing file: %s", path);
|
||||
// ensure path is not empty, or root dir
|
||||
if(!path || strlen(path) == 0 || strcmp(path, "/") == 0){
|
||||
Serial.println("Invalid path provided");
|
||||
out.println("Invalid path provided");
|
||||
} else {
|
||||
bool is_fs2 = false;
|
||||
if (memcmp(path, "UserData/", 9) == 0) {
|
||||
@@ -2326,23 +2321,115 @@ void MyMesh::checkCLIRescueCmd() {
|
||||
removed = _store->removeFile(path);
|
||||
}
|
||||
if(removed){
|
||||
Serial.println("File removed");
|
||||
out.println("File removed");
|
||||
} else {
|
||||
Serial.println("Failed to remove file");
|
||||
out.println("Failed to remove file");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if (strcmp(cli_command, "reboot") == 0) {
|
||||
} else if (strcmp(command, "reboot") == 0) {
|
||||
board.reboot(); // doesn't return
|
||||
} else {
|
||||
Serial.println(" Error: unknown command");
|
||||
out.println(" Error: unknown command");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MyMesh::checkCLIRescueCmd() {
|
||||
int len = strlen(cli_command);
|
||||
while (Serial.available() && len < sizeof(cli_command)-1) {
|
||||
char c = Serial.read();
|
||||
if (c != '\n') {
|
||||
cli_command[len++] = c;
|
||||
cli_command[len] = 0;
|
||||
}
|
||||
Serial.print(c); // echo
|
||||
}
|
||||
if (len == sizeof(cli_command)-1) { // command buffer full
|
||||
cli_command[sizeof(cli_command)-1] = '\r';
|
||||
}
|
||||
|
||||
if (len > 0 && cli_command[len - 1] == '\r') { // received complete line
|
||||
cli_command[len - 1] = 0; // replace newline with C string null terminator
|
||||
handleRescueCommand(cli_command, Serial);
|
||||
cli_command[0] = 0; // reset command buffer
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
#ifndef RECOVERY_AP_SSID
|
||||
#define RECOVERY_AP_SSID "EastMesh-WiFi"
|
||||
#endif
|
||||
#ifndef RECOVERY_CLI_PORT
|
||||
#define RECOVERY_CLI_PORT 23
|
||||
#endif
|
||||
|
||||
void MyMesh::startRecoveryAP() {
|
||||
if (_recovery_ap_active) return;
|
||||
|
||||
char ap_pwd[12];
|
||||
const char* pwd = NULL;
|
||||
if (_prefs.ble_pin != 0) { // WPA2 needs >= 8 chars, so zero-pad the pin
|
||||
sprintf(ap_pwd, "%08lu", (unsigned long) _prefs.ble_pin);
|
||||
pwd = ap_pwd;
|
||||
}
|
||||
|
||||
WiFi.mode(_prefs.wifi_ssid[0] ? WIFI_AP_STA : WIFI_AP); // keep trying STA if creds exist
|
||||
WiFi.softAP(RECOVERY_AP_SSID, pwd);
|
||||
|
||||
if (_rescue_server == NULL) {
|
||||
_rescue_server = new WiFiServer(RECOVERY_CLI_PORT);
|
||||
}
|
||||
_rescue_server->begin();
|
||||
rescue_cmd[0] = 0;
|
||||
_recovery_ap_active = true;
|
||||
|
||||
Serial.printf("WiFi: recovery AP '%s' up (%s), rescue CLI on %s:%d\n", RECOVERY_AP_SSID,
|
||||
pwd ? "pwd = pin zero-padded to 8 digits" : "OPEN - use 'set pin' to secure",
|
||||
WiFi.softAPIP().toString().c_str(), RECOVERY_CLI_PORT);
|
||||
}
|
||||
|
||||
void MyMesh::stopRecoveryAP() {
|
||||
if (!_recovery_ap_active) return;
|
||||
if (_rescue_client) _rescue_client.stop();
|
||||
_rescue_server->stop();
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
_recovery_ap_active = false;
|
||||
Serial.println("WiFi: recovery AP stopped");
|
||||
}
|
||||
|
||||
void MyMesh::loopRecoveryAP() {
|
||||
if (!_recovery_ap_active) return;
|
||||
|
||||
if (!_rescue_client || !_rescue_client.connected()) {
|
||||
WiFiClient next = _rescue_server->available();
|
||||
if (next) {
|
||||
_rescue_client = next;
|
||||
rescue_cmd[0] = 0;
|
||||
_rescue_client.print("========= CLI Rescue =========\r\n");
|
||||
}
|
||||
}
|
||||
if (_rescue_client && _rescue_client.connected()) {
|
||||
int len = strlen(rescue_cmd);
|
||||
while (_rescue_client.available()) {
|
||||
char c = _rescue_client.read();
|
||||
if (c == '\r' || c == '\n') {
|
||||
if (len > 0) {
|
||||
handleRescueCommand(rescue_cmd, _rescue_client);
|
||||
rescue_cmd[0] = 0;
|
||||
len = 0;
|
||||
}
|
||||
} else if (c >= 32 && c < 127 && len < (int) sizeof(rescue_cmd) - 1) {
|
||||
rescue_cmd[len++] = c; // printable chars only (filters telnet negotiation bytes)
|
||||
rescue_cmd[len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void MyMesh::checkSerialInterface() {
|
||||
size_t len = _serial->checkRecvFrame(cmd_frame);
|
||||
if (len > 0) {
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "DataStore.h"
|
||||
#include "NodePrefs.h"
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#include <RTClib.h>
|
||||
#include <helpers/ArduinoHelpers.h>
|
||||
#include <helpers/BaseSerialInterface.h>
|
||||
@@ -98,6 +102,13 @@ public:
|
||||
const char* getWifiSSID() const { return _prefs.wifi_ssid; }
|
||||
const char* getWifiPassword() const { return _prefs.wifi_pwd; }
|
||||
uint8_t getWifiPowerSaveMode() const { return _prefs.wifi_powersave; }
|
||||
#if defined(WIFI_SSID)
|
||||
// recovery AP: broadcast our own SSID (with rescue CLI on TCP) while STA can't connect
|
||||
void startRecoveryAP();
|
||||
void stopRecoveryAP();
|
||||
void loopRecoveryAP();
|
||||
bool isRecoveryAPActive() const { return _recovery_ap_active; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void loop();
|
||||
@@ -206,8 +217,12 @@ private:
|
||||
}
|
||||
|
||||
void checkCLIRescueCmd();
|
||||
void handleRescueCommand(char* command, Stream& out);
|
||||
void checkSerialInterface();
|
||||
bool isValidClientRepeatFreq(uint32_t f) const;
|
||||
#if defined(ESP32)
|
||||
void applyStationMode();
|
||||
#endif
|
||||
|
||||
// helpers, short-cuts
|
||||
void saveChannels() { _store->saveChannels(this); }
|
||||
@@ -230,6 +245,12 @@ private:
|
||||
bool _cli_rescue;
|
||||
bool send_unscoped; // force un-scoped flood (instead of using send_scope)
|
||||
char cli_command[80];
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
bool _recovery_ap_active = false;
|
||||
WiFiServer* _rescue_server = NULL;
|
||||
WiFiClient _rescue_client;
|
||||
char rescue_cmd[80];
|
||||
#endif
|
||||
uint8_t app_target_ver;
|
||||
uint8_t *sign_data;
|
||||
uint32_t sign_data_len;
|
||||
|
||||
@@ -111,6 +111,10 @@ void halt() {
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
bool wifi_needs_reconnect = false;
|
||||
unsigned long last_wifi_reconnect_attempt = 0;
|
||||
unsigned long last_wifi_connected = 0;
|
||||
#ifndef RECOVERY_AP_TIMEOUT_MS
|
||||
#define RECOVERY_AP_TIMEOUT_MS 60000 // STA not connected this long -> recovery AP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
@@ -278,5 +282,19 @@ void loop() {
|
||||
WiFi.reconnect();
|
||||
last_wifi_reconnect_attempt = millis();
|
||||
}
|
||||
|
||||
// Recovery AP: broadcast our own SSID (with the rescue CLI on TCP) when STA has no
|
||||
// credentials or hasn't been able to connect, so wifi.ssid/pwd can be fixed in place
|
||||
if (the_mesh.isRecoveryAPActive()) {
|
||||
the_mesh.loopRecoveryAP();
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
the_mesh.stopRecoveryAP(); // STA is up again; back to normal operation
|
||||
}
|
||||
} else if (WiFi.status() == WL_CONNECTED) {
|
||||
last_wifi_connected = millis();
|
||||
} else if (the_mesh.getWifiSSID()[0] == 0 ||
|
||||
millis() - last_wifi_connected > RECOVERY_AP_TIMEOUT_MS) {
|
||||
the_mesh.startRecoveryAP();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -105,8 +105,14 @@ SPIClass* getBoardSharedArchiveSPI() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ESP32)
|
||||
#define ARCHIVE_DEFAULT_SPI_BUS HSPI
|
||||
#else
|
||||
#define ARCHIVE_DEFAULT_SPI_BUS 0
|
||||
#endif
|
||||
|
||||
ArchiveStorage::ArchiveStorage()
|
||||
: _attempted(false), _mounted(false), _mount_failed(false), _supported(false), _card_type(0), _spi_bus(HSPI),
|
||||
: _attempted(false), _mounted(false), _mount_failed(false), _supported(false), _card_type(0), _spi_bus(ARCHIVE_DEFAULT_SPI_BUS),
|
||||
_cs_pin(0xFF), _sck_pin(0xFF),
|
||||
_miso_pin(0xFF), _mosi_pin(0xFF), _card_size_bytes(0), _total_bytes(0), _used_bytes(0)
|
||||
#if defined(ESP32)
|
||||
@@ -115,6 +121,7 @@ ArchiveStorage::ArchiveStorage()
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
namespace {
|
||||
|
||||
bool mountArchiveSd(SPIClass* spi,
|
||||
@@ -137,6 +144,7 @@ bool mountArchiveSd(SPIClass* spi,
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
void ArchiveStorage::begin() {
|
||||
if (_attempted) {
|
||||
|
||||
Reference in New Issue
Block a user