• Система автоматизации с открытым исходным кодом на базе 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;
}
Вот с этим я и продолжу играться. Спасибо за советы. Ушёл эксперементировать. О результате обязательно отпишусь.
 
Сверху Снизу