Парсинг Get запроса на сервер Arduino

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AndreyD пишет:

BOOM пишет:

Ну а причем тут клиент тогда? (особо в код не вчитывался)

http://www.joyta.ru/12628-sozdanie-prostogo-veb-servera-nodemcu-esp8266-v-arduino-ide/

Читай.

Почитаю. Но уточню, nodeMCU на данный момент у меня точка доступа (позже в планах добавить настройку на подключение к произвольному wifi роутеру), сейчас должно работать без роутера. Веб сервера на nodeMCU не будет, будет управляться POST запросами. Ну это как я вижу, ещё разбираюсь.

если к произвольному в пределах доступных пользуй вифимульти, проверено, работает с полтычка

AndreyD
AndreyD аватар
Offline
Зарегистрирован: 07.10.2018

ua6em пишет:

если к произвольному в пределах доступных пользуй вифимульти, проверено, работает с полтычка

У меня пока только идея, логика такая:

1. если nodeMCU не нашла "знакомого" роутера, то запускается как точка доступа.

2. Подключаемся к ней как к точке доступа, POST запросом пишем в EEPROM sid и password "местной" сети. Передёргиваем питание.

3. подключаемся уже через "местную" сеть.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AndreyD пишет:

ua6em пишет:

если к произвольному в пределах доступных пользуй вифимульти, проверено, работает с полтычка

У меня пока только идея, логика такая:

1. если nodeMCU не нашла "знакомого" роутера, то запускается как точка доступа.

2. Подключаемся к ней как к точке доступа, POST запросом пишем в EEPROM sid и password "местной" сети. Передёргиваем питание.

3. подключаемся уже через "местную" сеть.

там памяти много можно добрых два-три десятка знакомых сетей забить

junior_developer
Offline
Зарегистрирован: 27.11.2017

Помогите пожалуйста разобраться, что здесь имеется ввиду
 

const bool retVal = bufPtr > 0; // запоминаем, была ли у нас строка

код из этой темы:

#define BUF_LEN	200	// Длина буфера

char buffer [BUF_LEN];

bool receiveCharacter(void) {
	static int bufPtr = 0; // Указатель следующего свобоного байта в приёмном буфере
	if (! Serial.available()) return false; // Если ничего не пришло, выходим сразу (строка не готова)
	const char c = Serial.read();           // Читаем символ
	if (c == '\n' || c == '\r') {           // Если прочитанный символ - конец строки, то 
		const bool retVal = bufPtr > 0; // запоминаем, была ли у нас строка
		buffer[bufPtr] = 0;             // пишем в буфер признак конца
		bufPtr = 0;                     // В следующий раз начнём с начала
		return retVal;                  // Строка сформирована
	}	
	buffer[bufPtr++] = c;	                // запоминаем вновь полученный символ
	if (bufPtr == BUF_LEN) {/* что-то делаем */} // Реакция на переполнение буфера (пока никакой)
	return false;	                        // строка не готова
}

void setup(void) {
	Serial.begin(57600);
}

// 
//  Здесь мы обязательно дергаем receiveCharacter
//  он получит символ (если пришёл) и вернёт истину
//	если строка полностью пришла. Пока он не вернул
//	истину не паримся. а занимаемся своими делами
//
void loop(void) {
	if (receiveCharacter()) Serial.println(buffer);
	//	...
	// что-то нужное и важное
}

retVal это константа или переменная? и что ей присваивается?  bufPtr - это переменная типа int. Она сравнивается с нулем? Иными словами, если bufPtr > 0  то есть bufPtr больше нуля, то присвоить значение TRUE, а если нет - FALSE? Верно?
Сначала выполняется сравнение, а потом - присвоение значения? А почему там const bool, а не bool?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

junior_developer пишет:
что здесь имеется ввиду

const bool retVal = bufPtr > 0; // запоминаем, была ли у нас строка

То, что написано, тут нет никаких подвохов и "двойного дна".

junior_developer пишет:
retVal это константа или переменная?

Слово "const" Вам ничего не говорит? Скажем так, это величина, которую, раз присвоив, нельзя изменять. Часто её называют константой, но у теоретиков идут холивары на эту тему.

junior_developer пишет:
что ей присваивается?

Ну, дык ...

junior_developer пишет:
если bufPtr > 0  то есть bufPtr больше нуля, то присвоить значение TRUE, а если нет - FALSE?

junior_developer пишет:
Сначала выполняется сравнение, а потом - присвоение значения?

Видимо, так. Сверьтесь с таблицей приоритетов операций на всякий случай.

junior_developer пишет:
А почему там const bool, а не bool?

Потому, что эту величину не планируется изменять.

AndreyD
AndreyD аватар
Offline
Зарегистрирован: 07.10.2018

Вот что у меня получилось с парсингом GET запроса.

Имена параметров передаются только строчными латински буквами не более nameSTR - 1, принимаемое значение параметров от 0 до 255.

Обновил.

#include <ESP8266WiFi.h>

#define lenArr(sizedArr) sizeof(sizedArr)/sizeof(*sizedArr)
constexpr uint8_t nameSTR = 16; // максимальная длинна имен параметров GET запроса + 1 для '\0'

const char* ssid = "LuminousBall";
const char* password = "12345678";
IPAddress local_IP(10, 10, 10, 1);
IPAddress gateway(10, 10, 10, 1);
IPAddress subnet(255, 255, 255, 0);
WiFiServer server(80);

constexpr char nameP[][nameSTR]{
  {"Error"}, // Зарезервированно для отправки кода ошибки в ответе.
  {"mode"},
  {"num"},
  {"bright"},
  {"red"},
  {"green"},
  {"blue"},
  {"speed"}
};
constexpr uint8_t lenNameP = lenArr(nameP);

void parsing(WiFiClient& client, uint8_t valueP[]) {
    static char c, nameStr[nameSTR]{};
    static uint8_t iNameP = 0, value = 0, iValue = 0;
    while (client.available()) {
        c = client.read();
        if (c == '?') {
            while (c != ' ' && c != -1) {
                c = client.read();
                if (c == '\n' || c == '\r') break; // Защита от внезапного конца строки
                if (c >= 'a' && c <= 'z' && iNameP < (nameSTR - 1)) { // Последние условие защита от переполнения буфера имён параметров
                    nameStr[iNameP] = c;
                    iNameP++;
                }
                if (c == '=') {
                    nameStr[iNameP] = 0;
                    iNameP = 0;
                    for (uint8_t i = 0; i < lenNameP; i++)
                        if (strcmp(nameP[i], nameStr) == 0) { iValue = i; break; }
                }
                if (c >= '0' && c <= '9') {
                    value = value * 10 + (uint8_t(c) - 48); // Защиты от переполнения нет
                }
                if ((c == '&' || c == ' ') && iValue) {
                    valueP[iValue] = value;
                    value = 0; iValue = 0;
                }
            }
        }
    }
    // Ответ в виде строки с полученными параметрами
    client.println(F("HTTP/1.1 200 OK"));
    client.println(F("Content-Type: text/plain"));
    client.println(F("Connection: close"));
    client.println();
    client.print('?');
    for (uint8_t i = 0; i < lenNameP; i++) {
        client.print(nameP[i]);
        client.print('=');
        client.print(valueP[i]);
        client.print('&');
    }
    client.println();
}

void setup() {
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(local_IP, gateway, subnet);
    WiFi.softAP(ssid, password);
    server.begin();
}

void loop() {
    static uint32_t clientMs = 0;
    static uint8_t valueP[lenNameP]{}; //массив для значений параметров
    uint32_t newMs = millis();

     if ((newMs - clientMs) >= 50UL) {
        clientMs = newMs;
        WiFiClient client = server.available();
        if (client) parsing(client, valueP);
    }
    
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Уважаю желание потренироваться, но намекаю, что класс WebServer для ESP уже имеет механизм парсинга GET/POST в аргументы. 

AndreyD
AndreyD аватар
Offline
Зарегистрирован: 07.10.2018

sadman41 пишет:

Уважаю желание потренироваться, но намекаю, что класс WebServer для ESP уже имеет механизм парсинга GET/POST в аргументы. 

В Гугле чёт не нашёл или не так искал.

В библиотеке ESP8266WebServer нашёл Parsing-impl.h, но не совсем понял что там.

Можно ещё подсказку?

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно. WebServer -> Examples -> AdvancedWebServer

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);
}