• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Парсинг POST запроса

YaSerg

New member
Всем привет.
Имеется задача передавать значение температуры и влажности с одного МК на другой.
Контроллеры уже общаются между собой простым сравнением строк indexOF.

Помогите прочитать запрос вида /t=24 и h=40. Требуется получить цифровое значение 24 для температуры и 40 для влажности.
 

=AK=

New member
Три раза перечитал, но в чем состоит вопрос - так и не понял. :(
 

enjoynering

Well-known member
все о парсинге string тут - Arduino Reference

вот пример парсинга URL и выуживания из него имя сервера

Код:
/************************************************************************************/
/*
    getHostName()

    Returns host name from URL

    NOTE:
    - for example we have url "ep257.hostingradio.ru:8052/europaplus257.mp3"
      then "ep257.hostingradio.ru" will be returned
*/
/************************************************************************************/
String getHostName(String urlAddress)
{
  uint8_t position = 0;

  position = urlAddress.indexOf("/");  //search for "/" extension separetion simbol simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without extension
    position = 0;                      //clear position
  }

  position = urlAddress.indexOf(":");  //search for ":" port separetion simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without port number
  }

  return urlAddress;
}
 

NeoroN

Member
И какое кодирование у вашего POST запроса?
application/x-www-form-urlencoded
multipart/form-data
text/plain
 

enjoynering

Well-known member
Похоже "не в коня корм". Зря мы тут стараемся. Человеку не нужна информация и помощь. Ему нужно чтоб за него все написали и в рот положили. Ардуино головного мозга, он такой. Расходимся.
 

NeoroN

Member
Я тут тренировался парсить простые запросы на Lua:
Код:
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
    local buffer = ""
    conn:on("receive", function(client,request)
        port, ip = client:getpeer()
        buffer = buffer..request
        local buf = ""
        local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP")
        if(method == nil)then
            _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP")
        end
        local _GET = {}
        local _POST = {}
        if (vars ~= nil)then
            for k, v in string.gmatch(vars, "(.[^=]*)=(.[^&]*)&*") do
                _GET[k] = v
            end
        end
        if(method == "POST")then
            _,_, vars = string.find(request, "\r\n\r\n(.+)$")
            for k, v in string.gmatch(vars, "(.[^=]*)=(.[^&]*)&*") do
                _POST[k] = v
            end
        end
        print("GET[]="..sjson.encode(_GET))
        print("POST[]="..sjson.encode(_POST))
        buf = 'HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: close\n\n<form action="/file?t=1&n=3" method="POST">'..
              '<input type="hidden" name="MAX_FILE_SIZE" value="30000" />'..
              'Отправить этот файл: <input name="userfile" type="file" />'..
              '<input type="submit" value="Send File" /></form>'
        client:send(buf)
    end)
    conn:on("sent", function (c) c:close() end)
end)
парсит только с кодированием application/x-www-form-urlencoded(которое по умолчанию)

я пробовал парсить и multipart/form-data но столкнулся с тем что надо вначале собрать куски данных и решил не заморачиваться.

На сишнике тоже можно, но надо библиотеки подрубать - регулярок то нет, a indexOf - уже муторно.
Да и готовые решения наверняка уже есть
 
Последнее редактирование:

YaSerg

New member
Я понял, что задал вопрос несколько не конкретизировав.

Кодирование запроса какое не знаю, но если это поможет: запросы отправляю через браузер и от esp к esp через роутер.

Я понимаю что для моих целей необходимо использовать ф-ции класса String, но какие именно не могу понять. Без практики мне сложно дается понимание.

К примеру задача следующая: если строка запроса (пример Т23) начинается с T, то считать в переменную int следующие символы или символы начиная со второго символа.

Подскажите какую ф-ции можно применить для данного условия.
 

enjoynering

Well-known member
я же вам привел простенький пример

Код:
/************************************************************************************/
/*
    getHostName()
    Returns host name from URL
    NOTE:
    - for example we have url "ep257.hostingradio.ru:8052/europaplus257.mp3"
      then "ep257.hostingradio.ru" will be returned
*/
/************************************************************************************/
String getHostName(String urlAddress)
{
  uint8_t position = 0;
  position = urlAddress.indexOf("/");  //search for "/" extension separetion simbol simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without extension
    position = 0;                      //clear position
  }
  position = urlAddress.indexOf(":");  //search for ":" port separetion simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without port number
  }
  return urlAddress;
}
 

NeoroN

Member
А он не хочет думать, регулярки взять тоже не хочет. У каждого свой кактус кторый он должен съесть. Хоть бы пример нормальный привел чего он там обработать хочет.
Код:
  String request = "POST / HTTP/1.1\r\nbla bla bla\r\n\r\nt=27&h=60"
  String t = "";
  String h = "";
  uint8_t post_data = request.indexOf("\r\n\r\n");
  uint8_t start = request.indexOf("t=", post_data);
  uint8_t end = request.indexOf("&", start);
  if(start > 0){
    if (end == -1){
      t = request.substring(start);
    }else{
      t = request.substring(start, end);
    }
  }
  start = request.indexOf("h=", post_data);
  end = request.indexOf("&", start);
  if(start > 0){
    if (end == -1){
      h = request.substring(start);
    }else{
      h = request.substring(start, end);
    }
  }
код чисто теоретический - на практике лень тестить(посмотрим заметит ошибку или нет).
 
Последнее редактирование:

=AK=

New member
К примеру задача следующая: если строка запроса (пример Т23) начинается с T, то считать в переменную int следующие символы или символы начиная со второго символа.
Если у вас есть строковая переменная, которую нужно парсить, то сделайте следующее:
- организуйте цикл, в котором в переменную типа char считываются по очереди все символы этой строки
- в теле цикла, если значение считанного символа равно '=', то
-- предыдущий символ ('t' или 'h') определяет тип значения, температура или влажность; если ни то ни другое, то текуший символ '=' игнорируете и парсите дальше
-- последуюшие символы, пока они цифровые (т.е. в диапазоне от '0' до '9') преобразуете в числа и накапливаете в переменной типа int
-- когда строка закончилась или пошли нецифровые символы, запоминаете накопленное значение как, соответственно, температурy или влажность
 
Последнее редактирование:

pvvx

Активный участник сообщества
Если у вас есть строковая переменная, которую нужно парсить, то сделайте следующее:
- организуйте цикл, в котором в переменную типа char считываются по очереди все символы этой строки
- в теле цикла, если значение считанного символа равно '=', то
-- предыдущий символ ('t' или 'h') определяет тип значения, температура или влажность; если ни то ни другое, то текуший символ '=' игнорируете и парсите дальше
-- последуюшие символы, пока они цифровые (т.е. в диапазоне от '0' до '9') преобразуете в числа и накапливаете в переменной типа int
-- когда строка закончилась или пошли нецифровые символы, запоминаете накопленное значение как, соответственно, температурy или влажность
Не выйдет, т.к. в POST всё шифровано, хотя-бы элементарным urlencoded:
POST (HTTP) — Википедия
а в самом заголовке от браузера встретить "b=" или подобное - вероятность 90%.
Придется разбирать всё, согласно RFC-ам... До куков, chunked и GZIP включительно :)
 
Последнее редактирование:

=AK=

New member
Я так понял, вы предлагаете перебрать массивом всю таблицу символов? Или всё-таки, возможно, есть какая-то ф-ция?
В стандартной ASCII кодировке цифры от 0 до 9 кодируются числами от 0х30 до 0х39 соответственно. Проверяете значение символа, если оно в диапазоне от 0х30 до 0х39 - значит, это цифра. После этого численное значение цифры получаете, вычтя из значения символа число 0x30.

Код:
if ((c >= 0x30) && (c <= 0x39))
{
  val = c - 0x30;
}
 

YaSerg

New member
я же вам привел простенький пример

Код:
/************************************************************************************/
/*
    getHostName()
    Returns host name from URL
    NOTE:
    - for example we have url "ep257.hostingradio.ru:8052/europaplus257.mp3"
      then "ep257.hostingradio.ru" will be returned
*/
/************************************************************************************/
String getHostName(String urlAddress)
{
  uint8_t position = 0;
  position = urlAddress.indexOf("/");  //search for "/" extension separetion simbol simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without extension
    position = 0;                      //clear position
  }
  position = urlAddress.indexOf(":");  //search for ":" port separetion simbol in the url
  if (position > 0)
  {
    urlAddress.substring(0, position); //host name without port number
  }
  return urlAddress;
}
В стандартной ASCII кодировке цифры от 0 до 9 кодируются числами от 0х30 до 0х39 соответственно. Проверяете значение символа, если оно в диапазоне от 0х30 до 0х39 - значит, это цифра. После этого численное значение цифры получаете, вычтя из значения символа число 0x30.

Код:
if ((c >= 0x30) && (c <= 0x39))
{
  val = c - 0x30;
}
Вот с этим я и продолжу играться. Спасибо за советы. Ушёл эксперементировать. О результате обязательно отпишусь.
 
Сверху Снизу