Получить большой get запрос и скормить его json библиотеке
- Войдите на сайт для отправки комментариев
Втр, 27/08/2019 - 20:47
Парни, кто подскажет, два дня гоняю микроконтроллер, не хватает навыков дойти до решения...
Необходимо взять тут https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20190705&json, потом распарсить.
Когда беру через GetString, в итоге получается обрубленный файл.
Нашел информацию, что можно большие данные получить через getStreamPtr, в Serial выводит все, но как это собрать в String не допру...
Пните в нужном направлении пожалуйта!
void largeString () { std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure); client->setInsecure(); HTTPClient https; if (https.begin(*client, "https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=20190705&json") ) { Serial.print("[HTTPS] GET...\n"); // start connection and send HTTP header int httpCode = https.GET(); if (httpCode > 0) { // HTTP header has been send and Server response header has been handled Serial.printf("[HTTPS] GET... code: %d\n", httpCode); // file found at server if (httpCode == HTTP_CODE_OK) { // get lenght of document (is -1 when Server sends no Content-Length header) int len = https.getSize(); // create buffer for read static uint8_t buff[128] = { 0 }; // read all data from server while (https.connected() && (len > 0 || len == -1)) { // get available data size size_t size = client->available(); if (size) { // read up to 128 byte int c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); // write it to Serial Serial.write(buff, c); if (len > 0) { len -= c; } } delay(1); } Serial.println(); Serial.print("[HTTPS] connection closed or file end.\n"); } } else { Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str()); } https.end(); } else { Serial.printf("Unable to connect\n"); } Serial.printf("Free RAM: %d\n", ESP.getFreeHeap()); Serial.println("Wait 5s before the next round..."); }
раз он через getString весь не берется - значит его в String собирать не нужно - все равно не войдет. Нужно приниматиь кусками и сразу парсить
А не подскажите, как
Serial
.write(buff, c) в line запихнуть?
DeserializationError error = deserializeJson(doc,line)
А не подскажите, как
Serial
.write(buff, c) в line запихнуть?
DeserializationError error = deserializeJson(doc,line)
а какой тип у line ?
String
сорри, сразу не вчитался в вопрос, теперь стало еще непонятнее.
Что куда запихнуть хотите?
Если по частям парсить, то подойдет надо взять данные тут Serial.write(buff, c), привести их к String line и уже дальше распарсить json.
DeserializationError error = deserializeJson(doc,line);
Если по частям парсить, то подойдет надо взять данные тут Serial.write(buff, c), привести их к String line и уже дальше распарсить json.
да вот я и не понял, как можно взять данные из write. Для того, чтобы взять данные из Сериал, используется функция read
Serial.write(buf, len) забыли, то просто пример. Как мне получить эти же данные из приведенного кода в String line
Нашел информацию, что можно большие данные получить через getStreamPtr, в Serial выводит все, но как это собрать в String не допру...
Просто поразительное у нас число людей, забаненных в гугле.
https://github.com/squix78/json-streaming-parser
В принципе конкретно в этом случае можно распарсить и самому прям при считывании посимвольно... делов то :)
Йухуу
Потратил три дня )) Проблема не в лени или нежелании набивать шишки, проблема в длительности поиска нужной дороги. Особенно обидно, когда на настройку сервера обновления ушло 30 минут, а на простой парсинг несколько суток.
ckret - приведенный вами пример никакой не парсинг....
Но ска. работает быстро. То что нужно.
Если я правильно понял, то проблема была в обработке большого объема json, а у вас вроде просто преобразование строки символов в число получилось. Да куда денется... конечно работать будет, просто выцепляет числа из потока символов, если формат json простой - может и сойдет, но вообще было бы очень желательно отлавливать в потоке метки/теги перед числами чтобы не промахнуться.
Но ска. работает быстро.
"Я печатаю 3000 знаков в минуту... но такая фигня получается" :)
У вас парсинг получился очень не специфический. Например, практически в любом среднего размера HTML обязательно попадется комбинация цифр "36" - после которого ваш код выцепит из входящего потока какой-то флоат, скорее всего не имеющий ни малейшего отношения к тем данным, что вам нужны
Йухуу
добавлю еще вот что - вышеприведенный код еще и работает не такк, как ожидается. Вам, скорее всего, нужно извлечь из json флоат, расположенный после цифр "959", так? - А этот код ищет во входящем потоке любой флоат, а не расположенный после 959...
В общем, сорри, но парсингом это не назовешь. Мне даже кажется, что условия поиска цифр можно вообще выкинуть, результат не поменяется
Файл json практически константа, поэтому нет ничего, что помешает логике поиска целого числа, с последующим взятием float. Как по мне, это один из наиболее быстрых способов, которые мне удалось получить за последние дни.
Файл json практически константа, поэтому нет ничего, что помешает логике поиска целого числа, с последующим взятием float.
в вашем коде нет "последующего взятия" флоат
скажите лучше, что вы так и не поняли, как скопировать строковый буфер в переменную и провести в ней поиск строки, поэтому и придумали эту ерунду
Впрочем, дело ваше. Когда вы поймете, что ваш метод дает ответ "через два раза на третий" - может измените мнение.
Я бы такое
ловил по тегам и после ":" брал значение до "," или конца строки, но в принципе да... если нужно только 2-3 валюты, то можно ловить их код и float за ним - с какой то вероятностью работать будет, но это ж блин криво )
Я бы такое
ловил по тегам и после ":" брал значение до "," или конца строки, но в принципе да... если нужно только 2-3 валюты, то можно ловить их код и float за ним - с какой то вероятностью работать будет, но это ж блин криво )
Morroc, как вы думаете, какой флоат извлечет ТС из такого json:
18.166 ? - а может 23.789 ?
Может и есть способ, который более эффективнее, но повторюсь, этот результат самое быстрое и компактное, что у меня получилось.
Список состоит из 13 валют.
Их индексы > 100, что исключает ошибочное срабатывание, поэтому в цикле сравниваем parseInt()), при совпадении берем первый за ним float и повторям.
в цикле сравниваем parseInt()), при совпадении берем первый за ним float
повторяю, ваш код работает не так
Morroc, как вы думаете, какой флоат извлечет ТС из такого json:
18.166 ? - а может 23.789 ?
Если последовательно выцопывать целое, потом флоат, опять целое... то по идее такого не будет, при сбое разве что (а даты не мешают читать числа, кстати ?), но идея ориентироваться только на числа в целом стремная.
Не понимаю, почему " ваш код работает не так", вроде бы все данные получаются... Возможно время 6 сек на обработку не такое маленькое, но к сожалению лучше пока добиться не смог.
Че то много 6 секунд или это вместе со временем запроса ?
Не понимаю, почему " ваш код работает не так", вроде бы все данные получаются...
Пока нет сбоев при получени ответа. Прилетит что то скособоченное - может распарситься криво.
Если последовательно выцопывать целое, потом флоат, опять целое... то по идее такого не будет
тут весь вопрос в том, смещается ли указатель буфера после выполнения client->parseInt() или следующий запрос снова начинает сначала? - я этого не знаю
По моей логике должен с начала начинать, тогда код ТС глючить будет. Если нет - тогда работать будет, но неустойчиво и криво, до первого сбоя. Или пока, к примеру, во каком-нить другом поле не попадется "36"
Правильно (на мой взгляд) искать уникальные идентификаторы и отталкиваться от них. А цифры в качестве идентификатоа нужного элемента - это до первого обновления выдачи (как верно выше заметили - само значение может быть равно 36 и что вернёт функция тогда?). Есть хорошая функция lastIndexOf() и substring(). Ими я бы и оперировал. Найти нужное выражение и отталкиваться от него.
Странно такое долгое время обработки. Или это вместе с запросами и ожиданием ответа?
5 секунд это без запроса, скорее всего это связанно с тем, что проверяется каждое полученное число на совпадению с 13 вариантами, думаю используя уникальные индентификаторы, как вы подметили, поможет сделать функцию более универсальной и сократить время в разы, скоро попробую.
скорее всего это связанно с тем, что проверяется каждое полученное число на совпадению с 13 вариантами
нет, сравнение каждого числа с 13 вариантами занимает буквально микросекунды. Основное время уходит на команды parseInt() и parseFloat(), поскольку в них есть встроенный таймаут. Каждый раз, когда эта команда не находит числа в тексте - она зависает на целую секунду. Время таймаута можно уменьшить, если вызвать функцию SetTimeout(x), где х - таймаут в мс Но еще правильнее эти две функции в серьезных программах избегать, это костыль для вебдизайнеров (читай для тех, кто Си не знает :).
Странное поведение функций - зависание на секунду. Зачем вообще такое может быть нужно? Тайм-аут для чего?
:))) Недооценил я мощности ESP ... Нормально так удочка помогла ))
Поставил 10 .
Затраченное время с запросом: 1250
Время обработки буфера: 115
Поставил 0
Затраченное время: 1179
Время обработки: 109
для уверенности, что число принято полностью. Например parseInt ждет на входе цифры, за которыми обязательно должны идти НЕ_ЦИФРОВЫЕ символы. Это нужно для определения, что ввод закончен. А если это не так - функция будет ждать секунду. чтобы не оказалось, что принятые цифры "25" - это на самом деле начало числа 25678
:))) Недооценил я мощности ESP ... Нормально так удочка помогла ))
вы о чем? - что за удочка?
что за удочка?
Тараканов из головы «выуживать» может?))
Каждая подксазка, это своего рода удочка рыбаку, а рыбу он должен сам ловить.
Вообще сарказм с тараканами не уместен. Написать код - это сложно, написать код не зная всех тонкостей, сложно втройне.
:))) Недооценил я мощности ESP ... Нормально так удочка помогла ))
Поставил 10 .
Затраченное время с запросом: 1250
Время обработки буфера: 115
Поставил 0
Затраченное время: 1179
Время обработки: 109
А куда вы эти цифры ставите? К иконе ближе? Я что то не соображу....