• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Не верная проверка на null

Const

Member
Привет. Использую библиотеку AsyncWiFiManager для подключения к wifi в которой есть возможность устанавливать кастомные параметры на страницу настроек подключения. Ниже код который я набросал для генерации ошибки.
C++:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESPAsyncWiFiManager.h>
#include "LittleFS.h"

AsyncWebServer server(80);
DNSServer dns;

void setup() {
    Serial.begin(115200);
    LittleFS.begin();
    AsyncWiFiManager wifiManager(&server, &dns);
    wifiManager.setDebugOutput(true);

    AsyncWiFiManagerParameter param_mqtt_title("<h3>Title</h3>");
    AsyncWiFiManagerParameter param_mqtt_checkbox("mqtt", "", "1", 1, " type=\"checkbox\"");
    AsyncWiFiManagerParameter param_mqtt_checkbox_label("<label for=\"mqtt\">Using MQTT</label>");
    AsyncWiFiManagerParameter div("<div></div>");
    AsyncWiFiManagerParameter param_mqtt_ip_label("<label for=\"mqtt_ip\">Mqtt ip:</label>");
    AsyncWiFiManagerParameter param_mqtt_ip("mqtt_ip", "0.0.0.0", "", 16, " type=\"text\" disabled");
    AsyncWiFiManagerParameter param_mqtt_port_label("<label for=\"mqtt_port\">Mqtt port:</label>");
    AsyncWiFiManagerParameter param_mqtt_port("mqtt_port", "1883", "1883", 5, " type=\"text\" disabled");
    AsyncWiFiManagerParameter param_mqtt_user_label("<label for=\"mqtt_user\">Mqtt user:</label>");
    AsyncWiFiManagerParameter param_mqtt_user("mqtt_user", "User", "", 16, " type=\"text\" disabled");
    AsyncWiFiManagerParameter param_mqtt_pass_label("<label for=\"mqtt_pass\">Mqtt password:</label>");
    AsyncWiFiManagerParameter param_mqtt_pass("mqtt_pass", "", "", 16, " type=\"text\" disabled");
    AsyncWiFiManagerParameter param_mqtt_script("<script>function b(d){mqtt_ip.disabled = mqtt_port.disabled = mqtt_user.disabled = mqtt_pass.disabled = d}mqtt.addEventListener('change', (event) => b(!mqtt.checked));</script>");

    wifiManager.addParameter(&param_mqtt_title);
    wifiManager.addParameter(&param_mqtt_checkbox);
    wifiManager.addParameter(&param_mqtt_checkbox_label);  
    wifiManager.addParameter(&div);
    wifiManager.addParameter(&param_mqtt_ip_label);
    wifiManager.addParameter(&param_mqtt_ip);
    wifiManager.addParameter(&param_mqtt_port_label);
    wifiManager.addParameter(&param_mqtt_port);
    wifiManager.addParameter(&param_mqtt_user_label);
    wifiManager.addParameter(&param_mqtt_user);
    wifiManager.addParameter(&param_mqtt_pass_label);
    wifiManager.addParameter(&param_mqtt_pass);
    wifiManager.addParameter(&param_mqtt_script);
   
    wifiManager.autoConnect(("Module-"+String(ESP.getChipId())).c_str());
}

void loop() {
}
Самый первый параметр 'param_mqtt_title' должен просто выводить HTML, но по каким то причинам текст который передан в конструктор вставляется в тег input. Я порылся в коде библиотеки и понял что условие
C++:
_params[i]->getID() != NULL
Возвращает true из за чего дальнейшее выполнение идет не по тому сценарию. В конструкторе
C++:
AsyncWiFiManagerParameter::AsyncWiFiManagerParameter(const char *custom)
{
  _id = NULL;
  _placeholder = NULL;
  _length = 0;
  _value = NULL;

  _customHTML = custom;
}
В поле _id устанавливается null и далее нигде не меняется.
 

Const

Member
Код:
Serial. println(_params[i]->getID());
ничего не выводит как при значении null.
C++:
_params[i]->getID() != NULL
Почему срабатывает это условие??? У меня кончились идеи как решить этот вопрос. Библиотека тут.
 

CodeNameHawk

Moderator
Команда форума
Самый первый параметр 'param_mqtt_title' должен просто выводить HTML
Где это видно?
Я вижу такое
Код:
class AsyncWiFiManagerParameter
{
public:
  AsyncWiFiManagerParameter(const char *custom);
  AsyncWiFiManagerParameter(const char *id,
                            const char *placeholder,
                            const char *defaultValue,
                            unsigned int length);
  AsyncWiFiManagerParameter(const char *id,
                            const char *placeholder,
                            const char *defaultValue,
                            unsigned int length,
                            const char *custom);
 

Const

Member
Где это видно?
Я вижу такое
Код:
class AsyncWiFiManagerParameter
{
public:
  AsyncWiFiManagerParameter(const char *custom);
  AsyncWiFiManagerParameter(const char *id,
                            const char *placeholder,
                            const char *defaultValue,
                            unsigned int length);
  AsyncWiFiManagerParameter(const char *id,
                            const char *placeholder,
                            const char *defaultValue,
                            unsigned int length,
                            const char *custom);
Первый параметр в моем примере использует один из конструкторов кот который вы показали. А именно - AsyncWiFiManagerParameter(const char *custom);
Перебор и формирование HTML из параметров начинается в цикле в стоке 959
C++:
for (unsigned int i = 0; i < _paramsCount; i++)
  {
    if (_params[i] == NULL)
    {
      break;
    }

    String pitem = FPSTR(HTTP_FORM_PARAM);
    if (_params[i]->getID() != NULL)
    {
      pitem.replace("{i}", _params[i]->getID());
      pitem.replace("{n}", _params[i]->getID());
      pitem.replace("{p}", _params[i]->getPlaceholder());
      snprintf(parLength, 2, "%d", _params[i]->getValueLength());
      pitem.replace("{l}", parLength);
      pitem.replace("{v}", _params[i]->getValue());
      pitem.replace("{c}", _params[i]->getCustomHTML());
    }
    else
    {
      pitem = _params[i]->getCustomHTML();
    }

    page += pitem;
  }
HTML должен формироваться в ветке else pitem = _params->getCustomHTML(); Но выполнение кода происходит в ветке if так как условие _params->getID() != NULL возвращает true и я не понимаю почему. Поле _id в конструкторе инициализируется в null.
 
Сверху Снизу