Веб-сервер Arduino POST получает переменные
Я научился считывать данные более низкого уровня при общении в Интернете.
В рамках большого проекта я тестирую веб-интерфейс.
До сих пор я мог отобразить основной веб-сайт и, увидев веб-адрес, прочитать данные из запроса GET.
Поскольку я собираюсь отправлять коды, я хочу использовать метод POST.
Я пытаюсь сделать это отдельным классом для своих будущих проектов, поэтому я отправляю только сам метод класса. (Позже он будет принимать содержимое веб-сайтов в виде строки, но сейчас входные переменные еще не реализованы)
Я использую esp8266, но предпочел бы избегать конкретных библиотек esp8266, поскольку я хочу, чтобы он в конечном итоге работал на эквиваленте Realtek.
Код:
uint8_t Stranky::Stav(String obsahStranky, uint8_t obnovovat){
WiFiClient client = server.available();
if (client) {
// HTTP-запрос заканчивается пустой строкой
char vstupRiadok[150]={'\0'};
uint8_t i=0;
bool currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
vstupRiadok[i]=c;
if(c=='\n' || i>=149) {
Serial.println(vstupRiadok);
//------------Извлекаем сюда переменные--------
for(uint8_t j=0; j<149; j++) {
//Serial.print(vstupRiadok[j]);
vstupRiadok[j]='\0';
}
i=0;
} else i++;
if (c == '\n' && currentLineIsBlank) {
Serial.println("Sending page");
client.println(ohlasSa(1,1));
client.println("<!DOCTYPE HTML>");
// отправляем стандартный HTTP-заголовок ответа
client.println("<html><head> <meta charset=\"utf-8\"></head><body>");
client.println("<h1> Nic nove</h1>");
client.println("<form method='POST'>");
client.println("Name:<input type=\"text\" id=\"Name\" name=\"Name\"/><br>\nSurname:<input type=\"text\" id=\"Surname\" name=\"Surname\"><br>\n<input type=\"submit\" value=\"Submit\"/><input type='reset'/> </form> </body>");
client.println("</html>");
break;
}
if (c == '\n') {
// вы начинаете новую строку
currentLineIsBlank = true;
} else if (c != '\r') {
// вы получили символ в текущей строке
currentLineIsBlank = false;
}
}
}
// дать веб-браузеру время для получения данных
delay(1);
// закрыть соединение:
client.stop();
Serial.println("Prehliadač dpojený");
}
}
В результате получается код браузера:
<!DOCTYPE HTML>
<html><head> <meta charset="utf-8"></head><body>
<h1> Nic nove</h1>
<form method='POST'>
Name:<input type="text" id="Name" name="Name"/><br>
Surname<input type="text" id="Surname" name="Surname"><br>
<input type="submit" value="Submit"/><input type='reset'/> </form> </body>
</html>
Когда я отправляю какие-либо данные через форму, они не принимаются, а получаются только следующие:
WS:ac
:ref 1
WS:av
:ref 2
:ur 2
:rn 469
POST / HTTP/1.1
Host: 192.168.43.209
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: sk,cs;q=0.8,ru;q=0.6,en;q=0.4,en-US;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://192.168.43.209/
Content-Type: application/x-www-form-urlencoded
Content-Length: 25
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sending page
Нет сообщений или переменных cookie, которые я мог бы извлечь
Я нахожусь далеко от дома, и у меня слишком мало данных, чтобы устанавливать другие программы, такие как wire-shark, через общий доступ к телефонной сети
@Tomas, 👍-1
Обсуждение2 ответа
Лучший ответ:
На основе кода дешифровщика я смог объединить его в работающий код
Проблема заключалась в том, что общение начинается с переменных заголовка, затем пустая строка, затем тело, содержащее переменные
Сначала установите соединение: и создайте базовые переменные
uint8_t Stranky::Stav(){
WiFiClient client = server.available();
if (client) {
// HTTP-запрос заканчивается пустой строкой
bool currentLineIsBlank = 0;
bool body=0; // Помогает увидеть, является ли это все еще заголовком
bool finished=0; // Чтобы узнать, прерывать ли соединение
uint8_t i = 0; // Чтобы итератор не сбрасывался в 0
char fullLine[81]={'\0'}; // буфер для ввода символа в строку
// символ *pch;
Serial.print("User connected\n");
while (client.connected()) {
while (client.available()) {
bool linEnd=0; // Когда работать со строкой (распечатать ее)
Получить один входящий символ:
char c = client.read();
Теперь сначала обработайте символ новой строки
Если бы последняя строка была пустой Это бы означало: Заголовок закончен и перемещается в тело входящих данных
Если не изменить currentLineIsBlank (пока новая строка не получит свой первый символ)
if(c=='\n') { если (currentLineIsBlank) { если(!тело) тело=1; текущаяЛайнИсБланк=0; } еще { Серийный. Распечатать("/"); текущаяЛайнИсБланк=1; ЛинЭнд=1; }
Теперь давайте рассмотрим любой другой символ, кроме новой строки:
if(c=='\n') {
if(currentLineIsBlank) {
if(!body) body=1;
currentLineIsBlank=0;
} else {
Serial. print("/");
currentLineIsBlank=1;
linEnd=1;
}
Убедитесь, что наш массив не переполняется
} else {
currentLineIsBlank=0; //If it has a character then its not empty
fullLine[i]=c;
i++; //Move to the next letter
}
Теперь, когда мы знаем, что происходит, мы можем предпринять какие-то действия после завершения строки буфера
если мы находимся на стадии тела, но еще не "закончили" отправку кода
if(i>=81) linEnd=1;
Начать извлечение символов из тела входящих данных.
В простой форме, такой как наша, переменные POST находятся в последней строке, поэтому мы просто продолжим переписывать строку
if(linEnd){
if(body && !finished) {
finished=1; // Finishing sending page
Serial.printf(F("Variables:\n\t"));
Наконец отправьте HTML-код веб-сайта:
uint8_t k=0;
while (client.available()) {
fullLine[k]=client.read();
Serial.printf(F("%c"),fullLine[k]);
if(k<80) k++;
if(fullLine[k]=='\n') {
k=0;
Serial.println();
}
}
// Here you can extract variables as shown in codebreakers' answer
Если мы еще не имеем дело с телом:
Serial.print("Sending page\n");
client.println(heatheRoutine()); //I have extra routine to inject heather so I do not have to write it every time I write a page
client.println("<!DOCTYPE HTML>");
// send a standard http response header
client.println("<html><head> <meta charset=\"utf-8\"></head><body>");
client.println("<h1>Fill the form now !!!</h1>");
client.println("<form method='POST'>");
client.println("Meno:<input type=\"text\" id=\"Name\" name=\"Name\"/><br>\nPriezvisko:<input type=\"text\" id=\"Surname\" name=\"Surname\"><br>\n<input type=\"submit\" value=\"Submit\"/><input type='reset'/> </form> </body>");
/*Serial.printf(F("Page source send\n"));*/
client.println("</html>\n");
break;
}
Если мы закончили то, что хотели, нам нужно выйти из цикла общения
currentLineIsBlank=1;
for(uint8_t j=0; j<i; j++) { //Print the last line
Serial.print(fullLine[j]);
fullLine[j]='/0'; //restore default values To prevent characters leaking into next line
}
Serial.println();
i=0; //Since we are on an end of a line we are starting from first position in a buffer
}
}
И закройте соединение:
if(finished) {
Serial.printf(F("Ending\n"));
break;
}
}
Полный код:
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("browser disconnected");
}
}
Проверьте свое определение
String vstupRiadok
такого быть не должно
String vstupRiadok=" "; //80 пробелов
Я бы все равно заменил его фиксированным символом приличного размера
char vstupRiadok[81] = {'\0'};
если вы создаете пустую строку или другой текст, не забудьте написать терминатор конца '\0'
и убедитесь, что массив символов равен +1 размеру самой длинной строки
Как класс String сам по себе является проблемой, как класс Arduino.
В созданном HTML-коде отсутствует
<head> <meta charset ="utf-8"></head>
ошибка в инструментах разработки. Кроме того, какой серверный код работает на Arduino, он не указан. Класс создает html-страницу, но, по крайней мере, в FF75 он пытается вызвать server.ip\odpoved - поэтому для декодирования этого маршрута должен быть какой-то код js или Arduino, поскольку из формы не прикреплены параметры.
EDITПроцедура извлечения будет выглядеть следующим образом:
bool currentLineIsBlank = true;
bool currentLineIsGet = true;
uint8_t tCount = 0;
char tBuf[64];
uint8_t n=0;
uint8_t s=0;
char *pch;
Serial.print("Client request: ");
while (client.connected()) {
while (client.available()) {
char c = client.read();
if (currentLineIsGet && tCount < 63) {
tBuf[tCount] = c;
tCount++;
tBuf[tCount] = 0;
}
if (c == '\n' && currentLineIsBlank) {
Serial.println(tBuf);
// получить данные POST
Serial.print("POST data: ");
while (client.available()) Serial.write(client.read());
Serial.println();
pch = strtok(tBuf, "?");
while (pch != NULL) {
if (strncmp(pch, "Name=", 5) == 0) {
pch = pch+6;
char Name [24] = {'\0'};
while(pch != '&'){
char Name [n] = pch;
n++;
}
char Name [n+1] = {'\0'};
Serial.print("Name="); Serial.println(Name);
}
if (strncmp(pch, "Surname=", 8) == 0) {
pch=pch+9;
char Surname[24] = {'\0'};
while(pch != '\r') { // проверяем, есть ли это в вашем ответе после содержимого или это '\0'
char Surname [s] = pch;
s++;
}
char Surname [s+1] = {'\0'};
Serial.print("Surname="); Serial.println(Surname);
}
pch = strtok(NULL, "& ");
}
// здесь начинается часть отправки ответа
Для этого вам не нужен синтаксический анализатор JSON, просто получите почтовый запрос
Комментарии не для расширенного обсуждения; этот разговор был [перемещен в чат](https://chat.stackexchange.com/rooms/106650/discussion-on-answer-by-codebreaker007-arduino-webserver-post-receive-varriables)., @VE7JRO
- Несколько клиентских серверов через Wi-Fi
- WebSocketsServer.h: No such file or directory
- Как получить данные из базы данных моего сервера в переменную в моем Arduino?
- Как получить параметры запроса от ESPAsyncWebServer?
- контент» не захватывается
- ESP32 в Arduino-IDE с FS.h и SPIFFS
- Веб-сервер Arduino: более быстрая альтернатива «indexof» для разбора запросов GET?
- Как разрешить междоменные запросы на ESP8266 WebServer
Я обнаружил, что мне нужно декодировать объект json, но как мне получить его из полученных данных?, @Tomas