Учетные данные WiFi, извлеченные с SD-карты, не работают, но работают, если они жестко запрограммированы?

Я пытаюсь перенести жёстко заданные учётные данные Wi-Fi (SSID/пароль) на SD-карту, чтобы их было проще менять, но при передаче SSID в функцию WiFi.begin() возникает ошибка с кодом состояния 1 — «WL_NO_SSID_AVAIL». Я даже дважды проверяю, нет ли дополнительных символов в конце SSID при чтении его из текстового файла на SD-карте. Значения, кажется, верны, но ошибка всё равно возникает. Кто-нибудь может понять, что я упускаю? Вот код, который я пытаюсь использовать:

#include <SPI.h>
#include <SD.h>
#include <WiFi.h>
#include <esp_now.h>
#include <vector>  // Включить векторную библиотеку

// Определить пин-код для устройства чтения SD-карт
#define SD_CS_PIN 5

// Переменные для хранения сетевых учетных данных и MAC-адресов
String ssid;
String password;
std::vector<uint8_t*> macAddresses;  // Динамический массив для хранения MAC-адресов

void setup() {
  Serial.begin(115200);

  // Инициализируем SD-карту
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialized.");

  // Открыть файл конфигурации
  File configFile = SD.open("/network.txt");

  if (!configFile) {
    Serial.println("Failed to open config file");
    return;
  }

  // Читаем файл построчно и анализируем значения
  while (configFile.available()) {
    String line = configFile.readStringUntil('\n');

    if (line.startsWith("SSID=")) {
      ssid = line.substring(5);
    } else if (line.startsWith("PASS=")) {
      password = line.substring(5);
    } 
  }

  configFile.close();
  delay(500); // Перед продолжением убеждаемся, что выполнение завершено

  // Отладка: вывод SSID и пароля на последовательный монитор — проверка конечных символов
  Serial.print("Connecting to SSID: '");
  Serial.print(ssid);
  Serial.println("'");

  Serial.print("Using Password: '");
  Serial.print(password);
  Serial.println("'");


  // Подключиться к Wi-Fi
  WiFi.disconnect(true); // Убеждаемся, что в данный момент нет установленных подключений
  delay(1000); 
  WiFi.begin(ssid.c_str(), password.c_str());

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("Current WiFi Status Code: ");
    Serial.println(WiFi.status());
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi");

void loop() {

}

Я пытался убедиться, что функция ввода-вывода с SD-картой завершается, добавляя задержку после команды close(), но это не помогло. Я также пробовал добавлять WiFi.disconnect() перед WiFi.begin() с задержкой, чтобы убедиться, что не устанавливается никаких других подключений. Наконец, я проверяю правильность SSID и PASS в последовательном мониторе и отсутствие пробелов в конце, которых я не видел в текстовом файле. Значения верны, но я всё ещё получаю код ошибки 1 или «WL_NO_SSID_AVAIL» после каждой попытки подключения. Когда я напрямую прописываю значения в коде, подключение проходит без проблем.

, 👍0

Обсуждение

Попробуйте trim() для ssid и password. Не уверен, что вы увидите solo \r в Serial Monitor., @Juraj

Это... сработало. Не могу поверить, что отладочная строка, выводящая строку, за которой сразу идёт одинарная кавычка, не отследила это. Я был уверен, что увижу хотя бы пробел перед кавычкой. Большое спасибо!, @radioloko

Опасности использования обычного текстового файла. В него могут проникнуть невидимые символы. Используйте JSON, например, для хранения настроек., @dda

Несмотря на то, что вы выводите SSID и пароль в Serial Monitor, при чтении с SD-карты к SSID или паролю могут добавляться скрытые символы (например, возврат каретки \r или лишние пробелы). Вы можете вручную обрезать скрытые символы с помощью функции trim()., @liaifat85


1 ответ


2

Благодаря Юраю, эта проблема решена. Используемый мной метод допускал возможность добавления непечатаемого символа в конце. Добавление 'ssid.trim();' после получения значения SSID и 'password.trim();' после получения значения пароля решило проблему.

,

Интересно. WiFi.begin(ssid.c_str(), password.c_str()); Вы [и @Juraj] также предполагаете (возможно, в данном случае верно), что метод begin хранит массивы символов, а не просто указатель на них, так что, скажем, последующие вызовы .begin() (без параметров) при необходимости будут работать. Некоторые функции ESP, например, configTime( , , char* NtpServerName ), требуют от пользователя предоставления статического хранилища для массива символов, и это не всегда очевидно без изучения библиотеки. Массив символов, предоставляемый .c_str(), хранится недолго., @6v6gt

@6v6gt Я не предполагаю. Я знаю., @Juraj