• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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.
 
Сверху Снизу