Ви не увійшли.
Добрый день,
На сервер Arduino отправляется get запрос вида:
GET /?username=Dessan&password=12345 HTTP/1.1
Сервер Ардуино принимает запрос и выводит в порт:
GET /?username=Dessan&password=12345 HTTP/1.1
Host: 192.168.0.177:5000
Connection: keep-alive
Accept: application/json, text/javascript, */*; q=0.01
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 YaBrowser/19.9.3.314 Yowser/2.5 Safari/537.36
Origin: null
Accept-Encoding: gzip, deflate
Accept-Language: uk,ru;q=0.9,en;q=0.8
Я хочу, чтоб в результате get запроса я получал отдельно username, отдельно Dessan, отдельно password и отдельно 12345 и мог с этими данными что-то делать, например сравнивать и выполнять какое-либо действие.
Весь get запрос записывается в переменную tempChar но она имеет свой непонятный мне формат и как я не пытался сделать её строковой у меня ничего не вышло. Я создал другую строковую переменную readString и присвоил ей содержимое tempChar. Насколько я понял, строковые переменные в Arduino являются сами по себе массивами. После манипуляций с indexOf и substring мне удалось распарсить нужную мне строку, однако она выводит не полностью слово , к примеру, username а начинает вывод по буквам.
Вот код парсинга строки:
String readString;
...
while (client.connected()) {
if (client.available()) {
tempChar = client.read();
//Serial.write(tempChar);
if (readString.length() < 100 ) {
readString += tempChar;
//Serial.print(readString.length());
ind1 = readString.indexOf("?");
ind2 = readString.indexOf("=");
teststring = readString.substring(ind1, ind2);
teststring.replace("?", " ");
teststring.trim();
...
Вот результат парсинга (значение в teststring):
u
us
use
user
usern
userna
usernam
username
username
username
username
username
username
username
и далее ещё штук 20 таких вот username
Получается , что если делать проверки содержит ли переменная username , то дальнейший код реагирует и на username и на u и на us и на use и т.д. В принципе оно работает, но хочется иметь нормальный код более менее а не совсем уже говнокод.
Неактивний
хочется иметь нормальный код
Для этого нужно либо научится нормально программировать самому, либо нанять нормального программиста, чтобы он сделал. Шакалить по форумам на халяву - не вариант. Тебя просто начнут посылать нах., как совершенно справедливо написано на лурке.
Неактивний
А это форум не для обсуждения разве? Я не знал, что тут только предлагают работу нормальным программистам. Хотя для нормального программиста тут вообще нечего делать
Это точно, нормальным программистам тут вообще нечего делать! Для разбора форматированных строк удобно использовать функцию sscanf(...). А если не хватает места "вышивать крестиками" методами класса String.
А эта функция sscanf(...) разве не только для числовых значений формата int? А то у меня числа с буквами вместе стоят
Не только для числовых. Для всяких. Читайте в руководствах и справочниках по С, как пользоваться.
Я б на Вашому місці створив дві змінні username та password а тоді б парсив GET запит присвоюючи змінним знайдені результати.
Наприклад:
String answer = client.readStringUntil('\r'); //Присвоєння зчитаних даних рядковій змінній answer
Далі у Вашому випадку:
if (answer.indexOf("username") != -1){
//Тут код для присвоєння на початку об`явленій змінній String username знайденого значення
}
if (answer.indexOf("password") != -1){
//Тут код для присвоєння на початку об`явленій змінній String password знайденого значення
}
Неактивний
Я делаю примерно так:
//------------------------------------------------------------------------------
void serverLoop()
{
EthernetClient client = server.available();
client.setTimeout(10000);
if (client)
{
while (client.connected())
{
workWithClient(client);
client.stop();
}
}
}
//------------------------------------------------------------------------------
void workWithClient(EthernetClient& client)
{
// Read headers and get filepath
String path;
String content;
String token;
HttpMethod method;
while (client.available())
{
const int length = client.readBytesUntil('\n', buffer, bufferSize - 1);
if (length <= 0)
break;
buffer[length] = '\0';
String line = String((char*)buffer);
line.trim();
if (line.startsWith("GET"))
{
method = httpGet;
path = extractFirst(line, "GET", "HTTP");
path.trim();
}
// Дальнейшая обработка используя extractFirst
// ...
}
}
//------------------------------------------------------------------------------
String extractFirst(const String& text, const String& startWord, const String& endWord)
{
const int startIndex = text.indexOf(startWord);
if (startIndex == -1)
return String();
int endIndex = text.indexOf(endWord, startIndex);
if (endIndex == -1)
return text.substring(startIndex + startWord.length());
return text.substring(startIndex + startWord.length(), endIndex - startIndex);
}
Остання редакція Avazart (2019-10-30 22:22:19)
Неактивний
Я б на Вашому місці створив дві змінні username та password а тоді б парсив GET запит присвоюючи змінним знайдені результати.
Наприклад:
String answer = client.readStringUntil('\r'); //Присвоєння зчитаних даних рядковій змінній answer
Далі у Вашому випадку:
if (answer.indexOf("username") != -1){
//Тут код для присвоєння на початку об`явленій змінній String username знайденого значення
}
if (answer.indexOf("password") != -1){
//Тут код для присвоєння на початку об`явленій змінній String password знайденого значення
}
Тут вопрос в том, что все данные могут быть разными. То есть вместо username может быть любой текст, как и вместо password
Неактивний
Я делаю примерно так:
//------------------------------------------------------------------------------
Как мне объяснил народ, плохая идея забивать сначала всё что приходит в буфер а потом парсить, потому что буфер слишком маленький и если будет много данных, то всё зависнет. Нужно парсить на лету
Неактивний
Так размер буфер нужно подбирать.
И именно поэтому стоит использовать Mega вместо UNO.
Если не ошибаюсь в строке HTTP запроса обычно не более 127 символов (Лучше посмотреть RFС) что должно вполне хватать под буфер для построчного чтения.
Остання редакція Avazart (2019-11-03 00:48:32)
Неактивний
Как мне объяснил народ, плохая идея забивать сначала всё что приходит в буфер а потом парсить, потому что буфер слишком маленький и если будет много данных, то всё зависнет. Нужно парсить на лету
Как пить дать зависнет. Просящий дожен писать так, чтобы можно было обслужить всё последовательно, без откладывания до поступления дополняющих инструкций. Но кто у нас так просить умеет? Всем давай всё с полуслова и сразу! А еще исполнитель может не успевать исполнить все желания. Это приводит к необходимости контроля потоков запросов, это типа как официант приностит блюда только после употребления предшествующих, едоком. Тут всё как в ресторане, только на другом языке.
А читать по байтику не зависнет? Не несите чушь.
Ведь все равно нужен буфер куда складывать и все равно нужно читать до перевода строки.
Остання редакція Avazart (2019-11-03 15:33:05)
Неактивний
А читать по байтику не зависнет? Не несите чушь.
Ведь все равно нужен буфер куда складывать и все равно нужно читать до перевода строки.
Чушь, сейчас, самая востребованная ноша. Её несут все и везде! Складывать пора вёсла, и браться за буфера! Их парсить проще, чем поток токенов.
ПоТамушта HTTP протокол, есть заголовки(headers) и тело(body). Заголовки идут строками(lines, т.е по разделителю CRLF). Соответственно логично анализировать именно по строкам, по крайней мере пока идут заголовки, тело потом можно читать как надо/угодно, но вообще в данном случае как правило можно тупо отбрасывать, игнорировать так как все интересное у нас содержится в самом URL в параметрах.
Остання редакція Avazart (2019-11-03 22:17:08)
Неактивний
логично анализировать именно по строкам
В заголовке http нет ничего, что могло бы, стоя в конце строки, отменить (или как-то повлиять на) то, что стояло в начале. Потому логично анализировать посимвольно, обычным лексическим автоматом. Построчно - это для тех, кто правильно делать не умеет.
Остання редакція Kaka (2019-11-04 10:57:15)
Неактивний
Не форум, а сборище флудеров. Если не знаете как решить задачу, так и не пишите ваши крайне умные мысли ни о чём. Хорошо, что у меня есть рабочее решение через функцию и даже без цикла while (что особенно приятно).
Avazart, за код спасибо, но он не подходит. Более того, длина HTTP запроса зависит от браузера и принимающего сервера и там точно не 127 символов. Через хром можно и 2000+ передать, а вот сколько может обработать сервер arduino за раз я не знаю. Но мне вполне хватит и 500 символов для всех целей.
Моя главная проблема в том, что я не знаю как подключить модули String и stdio в ардуино, в стандартных библиотеках его нет. На западных форумах нашёл, что их качают и устанавливают. Зачем они мне нужны? Хочу понимать как они работают. Вроде что-то скачал, но они не подсвечены совсем в коде красным цветом, как остальные модули и я не знаю так должно быть или нет. К тому же я не понимаю как работают строки, почему вдруг они являются массивами и как из строки сделать цельное слово. Спросить не у кого. На форумах одни юмористы и умники.
Скачал Visual Studio - изучаю строки в С++, а там видно будет.
Неактивний
я не знаю как подключить модули String и stdio в ардуино, в стандартных библиотеках его нет.
В студии нет stdio.h ??? А если найду? Пиши #include <stdio.h> и не выпендривайся.
Неактивний
Dessan пише:я не знаю как подключить модули String и stdio в ардуино, в стандартных библиотеках его нет.
В студии нет stdio.h ??? А если найду? Пиши #include <stdio.h> и не выпендривайся.
Ок, оно должно подсвечиваться как-то?Почему все модули красным цветом а #include <stdio.h> чёрным?Или это ни на что не влияет?
Неактивний
Не форум, а сборище флудеров. ... я не понимаю как работают строки, почему вдруг они являются массивами и как из строки сделать цельное слово. Спросить не у кого. На форумах одни юмористы и умники.
Скачал Visual Studio - изучаю строки в С++, а там видно будет.
Про флудеров и юмористов это точно. Вы хоть один учебник прочитали? Например этот: https://proklondike.net/books/cpp/cplus_dlja_chainikov.html Строка в С/С++ это и есть массив символов, только всегда завершающийся терминальным символом равным нулю. А класс String это слишком долгий разговор для форума.
Avazart, за код спасибо, но он не подходит. Более того, длина HTTP запроса зависит от браузера и принимающего сервера и там точно не 127 символов. Через хром можно и 2000+ передать, а вот сколько может обработать сервер arduino за раз я не знаю. Но мне вполне хватит и 500 символов для всех целей.
Та конкретно в Вашем случае как за программировать столько и будет символов, все остальное можно отсекать. 500 символов явно много, лучше используйте POST
Строка в С/С++ это и есть массив символов, только всегда завершающийся терминальным символом равным нулю. А класс String это слишком долгий разговор для форума.
В С++ есть std::string который обычно используется.
Остання редакція Avazart (2019-11-05 12:51:18)
Неактивний