• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP8266 получение и обработка команд

PAV

Member
Друзья. Увеличиваю функционал своего IOT. Пришло время обрабатывать команды извне вида http://172.22.16.66/command?1,255 где commandReceived - 1, parametersReceived - 255
Т.е. при получении такой строки ESP должна распарсить строчку и присвоить commandReceived - 1 parametersReceived - 255
Код ниже. Кроме этой функции все работает исправно. Как только подключаю эту функцию, при компиляции пишет -
WebServer:4: error: 'class ESP8266WebServer' has no member named 'available'
WiFiClient client = server.available();

Подключены библиотеки:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

Не могу понять, что не так. Помогите, пожалуйста.

Код:
void WebServer(){
  //WEB Server - сервер ждет команды от МЖД вида http://172.22.16.66/command?1,255 где commandReceived - 1,  parametersReceived - 255.  Например потом использовать, как Pin1 = 255
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }


    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
      while (client.connected()) {
      if (client.available()) {
        char c = client.read();
           if (url.length() < maxLength) {
             url+=(c);
           }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
                
          Serial.print("HTTP request: ");
          Serial.println(url);
          if (url.indexOf("?")>=0) {

            int PosB=url.indexOf("?")+1;
            int PosE=url.indexOf("HTTP");
            if (url.indexOf(",")>=0) {
              // command has parameters            
              int PosP=url.indexOf(",");
              commandReceived=url.substring(PosB,PosP);            
              parametersReceived=url.substring(PosP+1,PosE-1);            
            } else {
              // command does not have parameters
              commandReceived=url.substring(PosB,PosE-1);            
              parametersReceived="";
            }
                                                                                                          //Serial.print("Command: ");
                                                                                                          //Serial.println(commandReceived);
                                                                                                          //Serial.print("Parameter: ");
            //char cstr[50];                                                                                              //Serial.println(parametersReceived);
            MDcommand = commandReceived.toInt();
            //parametersReceived.toCharArray(cstr,50);
           MDparameter = parametersReceived.toInt();
            //MDparameter=atol(cstr);
            //Serial.print("parameterRecieved");
            //Serial.println(parametersReceived);
           
                                                                                                         //Serial.print("MDCommand: ");
                                                                                                        //Serial.println(MDcommand);
                    
          
          }
        
        
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html><head><title>Arduino</title></head><body>");
          client.println("</body><html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }// end if (client.available())
    } //END while (client.connected())
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    url = "";
    client.stop();
    client.flush();
     Serial.println("client disconnected");


if (MDcommand == 1) {//Включить свет в холле
Serial.println("Web request");
}

}
 

PAV

Member
Вопрос снят.
Учитывая использование вышеприведенных библиотек, обработку запроса надо производить в void handleNotFound()
 

CodeNameHawk

Moderator
Команда форума
Учитывая использование вышеприведенных библиотек, обработку запроса надо производить в void handleNotFound()
Нутром чую, что не правильно.

https://esp8266.ru/forum/threads/esp8266webserver-biblioteka.1150/
Возможно подейдет, что то из этого
Код:
  String arg(String name);        // get request argument value by name
  String arg(int i);              // get request argument value by number
  String argName(int i);          // get request argument name by number
  int args();                     // get arguments count
  bool hasArg(String name);       // check if argument exists
Рекомендую посмотреть ESP8266 в среде Arduino IDE - YouTube
 
Последнее редактирование:

PAV

Member
Нутром чую, что не правильно.
Подвела чуйка. Все работает.
Код конечно переработал, ибо он под Arduino, но в общем и целом из кода мне нужен только раздел парсинга строки.
А строка получается url = server.uri();
А при использовании библиотеки ESP8266WebServer.h server.handleClient(); обращается к handleNotFound() или к handleRoot() в зависимости от ситуации. В нашем случае обработка запросов должна прописываться в handleNotFound()
 

valerivp

Member
Подвела чуйка. Все работает.
Код конечно переработал, ибо он под Arduino, но в общем и целом из кода мне нужен только раздел парсинга строки.
А строка получается url = server.uri();
А при использовании библиотеки ESP8266WebServer.h server.handleClient(); обращается к handleNotFound() или к handleRoot() в зависимости от ситуации. В нашем случае обработка запросов должна прописываться в handleNotFound()
Это не самый лучший вариант. Почему бы не написать обработчик URL "command"?
И я бы рекомендовал команды делать текстовые, чтобы когда команд будет больше 3 в них не путаться. Свои мысли по этому поводу я изложил: https://esp8266.ru/forum/threads/ra...ere-kontrollera-teplogo-pola-na-esp8266.3452/
 

PAV

Member
Это не самый лучший вариант. Почему бы не написать обработчик URL "command"?
Так там и есть обработчик. На ардуине обрабатывает более 30 разных команд с параметрами.
Например - свет в холле 1,255 1 - вызывает функцию свет в холле, 255 яркость
Отправить rf433 10, 362346 10-вызывает функцию rf433, 362346 радиокод
Это все в majordomo прописывается и потом не заморачиваешься.


Другое дело, что пришлось слегка изменить строку запроса. Теперь выглядит так - 10.0.0.111/command=1,255END. Ну проще так парсить.

Ах, да, забыл написать почему поменял синтаксис - server.uri не видит знак ?
Теперь, по логике, считывает первое значение от знака = до знака , и второе значение со знака , до END
Просто и эффективно.
 
Последнее редактирование:

valerivp

Member
Так там и есть обработчик.
Вы написали что обрабатываете в NotFound
В нашем случае обработка запросов должна прописываться в handleNotFound()
Я же рекомендую делать отдельные обработчики:
Код:
    //list wifi networks
    help_info.concat(F("/wifi-scan ? [format=json]: get wifi list as text or json. Allow methods: HTTP_GET\n"));
    server.on("/wifi-scan", HTTP_GET, handleWiFiScan);

    help_info.concat(F("/wifi-info ? [format=json]: get wifi info as text or json. Allow methods: HTTP_GET\n"));
    server.on("/wifi-info", HTTP_GET, handleWiFiInfo);
 

PAV

Member
Зачем парсить то, что библиотека парсит сама? Аргументы и параметры я имею в виду.
Так же имеет смысл посмотреть функцию strtok
А какой должен быть вид строки, чтобы получить аргументы? Я так понимаю парсит аргументы server.args(); А в каком виде их нужно отправлять? Ну там с вопросиком, плюсиком, равно? Можете кусочек кода дать? Мне нужно, по сути, два параметра. Вот на ESP передать 1 и 255 в одном запросе. Как лучше/проще?
 

PAV

Member
гланды тоже можно вырезать через задний проход, но это не правильно.
Но можно же ;) Рабочий вариант. Я, как полный нуб в ESP8266 выкрутился просто. А дельные советы я всегда приветствую и стараюсь учиться. Заметьте, ДЕЛЬНЫЕ.
И потом, запрос обрабатывается именно в handleNotFound(),


@valerivp Спасибо тебе большое, добрый человек, все работает отлично. Век живи, век учись. Разработчики, к сожалению не любят вставлять примеры в описание, а зря, очень зря, столько бы времени сэкономили пользователям.
 

PAV

Member
Зачем парсить то, что библиотека парсит сама? Аргументы и параметры я имею в виду.
Так же имеет смысл посмотреть функцию strtok
Не подскажите по strtok? Int я распарсил MDcommand = server.arg(0).toInt();
А как распарсить параметр, который Long?
 

PAV

Member
Дорогие ГУРУ!!!! Очень вас прошу, объясняйте нормальным языком, с примерами!!!! Сегодня ноябрь 2022 и до меня только дошло, что вы хотели сказать в предыдущих сообщениях. Всего пять лет прошло. Теперь я понимаю, где я был не прав и как надо правильно делать ;) Да, я понимаю, что это мой косяк не читать мануалы, но я не программер от слова совсем и то, что для вас элементарно, для меня, как и 90% других, кто работает с ESP, это темный лес. Переписывать код уже не буду, наверное, но в новых проектах буду делать правильно.

В итоге. Для сервера пишем обработчик обращений:
Код:
void server_init(void) {
  server.on("/", handleRoot);    // Что делать, если запрос http://10.0.0.103
  server.on("/command", handleCommand); // Что делать, если запрос ttp://10.0.0.103/command?command=LED&param=1 
  server.on("/restart", handleRestart); // Перезагрузка модуля по запросу вида http://10.0.0.103/restart?device=ok
  server.onNotFound(handleNotFound);  //Что показывать, если запрос не обращается ни к какой странице (ошибочный)
  server.begin();
  Serial.println ( "HTTP server started" );
Соотв, раздел /command обрабатывается, когда сервер получает строку вида - http://10.0.0.103/command?command=LED&param=1

Дальше пишем обработчик этого раздела.
Код:
void handleCommand(){
  unsigned long param;
  String command;
  command = server.arg("command");
  param   = atol(server.arg("param").c_str());
  if (command == "LED") {
    Serial.print("LED - ");
    Serial.println(param);
  }
  server.send(200, "text/plain", "OK");
}
Соответственно, по тексту - получили строку вида http://10.0.0.103/command?command=LED&param=1 - увидели command? - отправили к обработчику handleCommand() - обработчик нашел команду command и нашел параметр param, присвоил значения переменным.
Дальше работаем с переменными и расписываем, что делать.
В данном случае пришла команда для LED изменить значение на 1.
 
Сверху Снизу