контент» не захватывается

Я пытаюсь создать переменную, которую можно будет изменять с сервера, используя ESP8266.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char* ssid = "********";
const char* password = "*********";

ESP8266WebServer server(80);

const int led = 13;

void handleRoot() {
    digitalWrite(led, 1);
    server.send(200, "text/plain", "hello from esp8266!");
    digitalWrite(led, 0);
}

void handleNotFound() {
    digitalWrite(led, 1);
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET)?"GET":"POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";

    for (uint8_t i=0; i<server.args(); i++){
        message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }

    server.send(404, "text/plain", message);
        digitalWrite(led, 0);
    }
}

void setup(void) {
    pinMode(led, OUTPUT);
    digitalWrite(led, 0);
    Serial.begin(115200);
    WiFi.begin(ssid, password);
    Serial.println("");

    // Ожидаем соединения
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());

    if (MDNS.begin("esp8266")) {
        Serial.println("MDNS responder started");
    }

    String content = "Basic";
    content += "<html><body><form action='action_page.php' method='POST'><br>";
    content += "User:<input type='text' name='USERNAME' placeholder='user name'>       <br>";
    content += "<input type='submit' name='SUBMIT' value='Submit'></form><br>";

    server.on("/led", [](){
        server.send(200, "text/html", content);
        Serial.println(USERNAME);
    }

    server.on("/", handleRoot);

    server.on("/inline", [](){
        server.send(200, "text/plain", "this works as well");
    });

    server.onNotFound(handleNotFound);
    server.begin();
    Serial.println("HTTP server started");
}

void loop(void){
    server.handleClient();
}

Когда я его компилирую, он говорит

"контент" не сохраняется

Я подумал, что это может быть из-за ввода, и для начала попытался назвать его «Базовым», но все равно не получилось.

, 👍2

Обсуждение

@jwpat7 Этот код (большая часть) взят из других примеров из библиотек, и я не (очень) хорош в этом, поэтому не могу понять, что вы подразумеваете под его исправлением., @Mihai Barbu

Возможно, [Лямбда лямбды: функция не захватывается](http://stackoverflow.com/q/13461538) будет более полезной, чем мой предыдущий комментарий., @James Waldby - jwpat7

И это будет использоваться здесь следующим образом: " server.on("/led" , [content](){..... " ?, @Mihai Barbu

Что-то в этом роде. Но я недостаточно знаком с лямбда-синтаксисом C++, чтобы сказать, возможно, кто-то еще знает., @James Waldby - jwpat7

Хорошо, я в любом случае не тороплюсь. Большое спасибо !, @Mihai Barbu


2 ответа


Лучший ответ:

3

Давайте рассмотрим более простой пример:

void setup ()
{
  String content = "Basic";

  attachInterrupt (digitalPinToInterrupt (2),
                   []()
  {
    Serial.println(content);
  }, 

  FALLING );

}  // конец настройки

void loop () { }

Это дает ошибку:

/tmp/arduino_modified_sketch_182173/sketch_jan25a.ino: In lambda function:
sketch_jan25a:8: error: 'content' is not captured
     Serial.println(content);

Почему? Потому что вы используете локальную переменную content в лямбда-функции, которая выполняется в глобальной области видимости. То есть, content недоступен для нее, потому что находится внутри setup.

Чтобы захватить его, вы можете поместить его в список захвата:

  attachInterrupt (digitalPinToInterrupt (2),
                   [content]()  // захват контента

Однако я обнаружил, что мой пример даже в этом случае не компилируется.


Я думаю, причину этого можно найти здесь: Лямбда-функции в C++11 - полное руководство

Как реализуются лямбда-замыкания?

Так как же на самом деле работает магия захвата переменных? Оказывается, лямбда-выражения реализуются путем создания небольшого класса; этот класс перегружает оператор(), так что он действует как функция. Лямбда-функция является экземпляром этого класса; когда класс создается, все переменные в окружающей среде передаются в конструктор класса лямбда-функции и сохраняются как переменные-члены.

Вы не можете передать экземпляр класса в attachInterrupt, поскольку существует скрытая переменная *this, которую необходимо передать экземплярам класса, а ISR этого не делают.

Ваш пример не является ISR, но, вероятно, применимы те же замечания.


Я не думаю, что здесь есть огромный смысл использовать лямбда-функции. Если вам это необходимо, переместите content внутрь лямбды, поскольку именно там вы его используете.

Или, если это невозможно, сделайте это глобальным.


Самое близкое, что я смог получить к чему-то компилируемому, это:

void setup ()
{
  const int content = 42;

  attachInterrupt (digitalPinToInterrupt (2),
                   [=]()
  {
    Serial.println(content);
  },

  FALLING );

}  // end of setup

void loop () { }

Честно говоря, я думаю, что использование лямбда-функций здесь просто делает ваш код непонятным.

,

Я написал led вместо lcd. Я пытаюсь сделать следующее: вызвать страницу из esp8266, которая дает мне поле ввода и кнопку отправки. Я хочу напечатать на lcd то, что написано в этом поле., @Mihai Barbu

Спасибо, это решило мою ошибку, но теперь у меня есть еще одна: 'void setup()': lcdWirelessPrint:69: ошибка: ожидается «)» перед «сервер» server.on("/", handleRoot); ^ статус выхода 1 «Пользователь» не был объявлен в этой области действия. Другой вопрос, как/где мне объявить имя переменной, которой я хочу присвоить имя входных данных., @Mihai Barbu

Это звучит как другой вопрос. Предлагаю вам начать новый вопрос и опубликовать этот новый код., @Nick Gammon

Ладно, я не хотел открывать слишком много, думал, что это будет раздражать., @Mihai Barbu


0

Вы смотрите на последнюю ошибку компилятора? Первая — самая важная. В настройках можно включить вывод компилятора, чтобы показать больше. Затем прокрутите вверх, чтобы увидеть первую ошибку компилятора. У компилятора проблемы с `` в самом конце вашего скетча.

,

Они нормальные», они изменились, когда я вставлял сюда. Я все равно завтра проверю., @Mihai Barbu