POST запрос работает на ESP32 и не работает на ESP8266. Помогите разобраться

p-a-h-a
Offline
Зарегистрирован: 17.01.2019


Один и тот же код заливаю и на ESP 8266 он не работает. По ощущениям не ждет ответа сервера или вообще запрос туда не шлет. Разница в #include <HTTPClient.h> и #include <ESP8266HTTPClient.h> Как портировать код?

/*#include <WiFi.h> //Первые две строки для ESP32 #include <HTTPClient.h> */ #include <ESP8266WiFi.h> // Эти две строки для ESP8266 #include <ESP8266HTTPClient.h> const char* ssid = "xxx"; const char* password = "xxx"; #include <ArduinoJson.h> //https://github.com/bblanchon/ArduinoJson #define debug true // вывод отладочных сообщений void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(100); } New_users(); } void New_users() { HTTPClient http; http.begin("https://api.telegram.org/botXXXXXXXXXXXXXXXX/"); http.addHeader("Content-Type", "application/json"); StaticJsonDocument<1000> doc; // Создаем и наполняем json для последующей отправки на сервер doc["method"]="getUpdates"; http.POST(doc.as<String>());// Json запрос на сервер String ans=http.getString(); Serial.println(ans); http.end(); } void loop() { }

 

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Неожиданно все слиплось в первом сообщении(

Один и тот же код заливаю и на ESP 8266 он не работает. По ощущениям не ждет ответа сервера или вообще запрос туда не шлет. 
Разница в #include <HTTPClient.h> и #include <ESP8266HTTPClient.h> Как портировать код?

 

/*#include <WiFi.h>
#include <HTTPClient.h>
*/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

const char* ssid = "xxx";
const char* password = "xxx";
#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson
#define debug true // вывод отладочных сообщений


void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("."); delay(100);
  }
  New_users();
  }

void New_users() {

  HTTPClient http;
  http.begin("https://api.telegram.org/botXXXXXXXXXXXXXXXX/");
  http.addHeader("Content-Type", "application/json");
  
  StaticJsonDocument<1000> doc; // Создаем и наполняем json для последующей отправки на сервер
  doc["method"]="getUpdates";
  http.POST(doc.as<String>());// Json запрос на сервер
  String ans=http.getString();
  Serial.println(ans);
  http.end();
  }

void loop() {
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Попробуй перед функцией setup() вставить такое:

void New_users();

 

rkit
Offline
Зарегистрирован: 23.11.2016

StaticJsonDocument<1000>

А чего не 1000000-то?

И почему бы тебе вместо ощущений не проверить наверняка?

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Докладываю:

ESP8266 и ESP32 по разному обращаются к httpS + ESP8266 требует пару строк инициализации

(#include <WiFiClient.h>,     WiFiClient client;)

и в строке запроса необходимо добавить слово client.

(http.begin(client, "http://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5"))

Но это не все. До httpS не достучатся т.к. проверка сертификата 8266 не проходит .

http.begin(client, "https://api.privatbank.ua/p24api/pubinfo?json&exchange&coursid=5")// это не работает

Ответ нашелся тут https://buger.dread.cz/simple-esp8266-https-client-without-verification-of-certificate-fingerprint.html Сразу приведу от туда пример по курсу биткоина через https с игнорированием SSL сертификатов

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

void setup() {
  Serial.begin(115200);
  Serial.println(F("\n\r* * * ESP BOOT * * *"));
  Serial.println(F("WiFi begin!"));
  WiFi.mode(WIFI_STA);
  WiFi.begin("SSID", "PASSWORD");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println(F("\n\rWiFi connected!"));
}

void getpr24h() {
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
  client->setInsecure();
  HTTPClient https;

  if (https.begin(*client, "https://blockchain.info/q/24hrprice")) {  // HTTPS
    Serial.println("[HTTPS] GET...");
    int httpCode = https.GET();

    // httpCode will be negative on error
    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) {
        String payload = https.getString();
        Serial.println(String("[HTTPS] Received payload: ") + payload);
        Serial.println(String("1BTC = ") + payload + "USD");
      }
    } else {
      Serial.printf("[HTTPS] GET... failed, error: %s\n\r", https.errorToString(httpCode).c_str());
    }

    https.end();
  } else {
    Serial.printf("[HTTPS] Unable to connect\n\r");
  }
}

void loop() {
  getpr24h();
  Serial.println("Wait 20s before next round to not get banned on API server...");
  delay(20000);
}

 

 

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

В esp32 AES256 - аппаратный (условно), в 8266 100% программный, тормоз, жесть. ESP32 - два ядра, поэтому на одном крутится сетевые дела, а остальную бурду, которую ты пишешь выполняют на втором ядре, 8266 - одно ядро, поэтому в код для 8266 нужно пихать например delay(0) , с таким расчетом, что бы код не загружал ядро дольше какого то периода, какого я уже не помню, ищи в даташитах. 

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Повторил этот код. Все работает, но!!!!

Слишком большой по длине ответ в payload. В результате в ряде случаев крах системы.

String payload = https.getString(); - вот здесь возникает крах.

Как этот самый payload забирать не весь сразу а порциями?

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

Как этот самый payload забирать не весь сразу а порциями?

не использовать String

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Пример приведите, тогда будет понятно.

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Я тогда много ковырял post запросы. Что помню: как вариант использовать масив char[]. Но это не вариант. Для post обмена данными есть замечательный формат json.
Вот тут (20я строка) с ним разбирался:
http://arduino.ru/forum/proekty/meteostantsiya-dlya-narodnogo-monitoring...

Ещё, очень часто в post запросе можно просить конкретную короткую инфу, к примеру курс валют не за год а за день или час. Тогда ответ короткий. Как это делать, нужно смотреть API сайта на который запрос уходит. Обычно в хэлпе сайта есть описание запросов (api).
Удачи.

b707
Offline
Зарегистрирован: 26.05.2017

p-a-h-a пишет:
помню: как вариант использовать масив char[]. Но это не вариант..

почему не вариант?

Берете массив char подходящей длины, например 200 символов.

Читаете из ответа сервера первые 200 символов, парсите... снова читаете 200 символов в ТОТ же массив...

В итоге вы можете прочитать ответ сервера хоть 10 мегабайт, имея один буфер 200 символов

AlexTVR
Offline
Зарегистрирован: 06.10.2018

b707 пишет:

p-a-h-a пишет:
помню: как вариант использовать масив char[]. Но это не вариант..

почему не вариант?

Берете массив char подходящей длины, например 200 символов.

Читаете из ответа сервера первые 200 символов, парсите... снова читаете 200 символов в ТОТ же массив...

В итоге вы можете прочитать ответ сервера хоть 10 мегабайт, имея один буфер 200 символов

Ну так пример приведите. Я его тут же и проверю. Или... никак.

AlexTVR
Offline
Зарегистрирован: 06.10.2018

p-a-h-a пишет:
Я тогда много ковырял post запросы. Что помню: как вариант использовать масив char[]. Но это не вариант. Для post обмена данными есть замечательный формат json. Вот тут (20я строка) с ним разбирался: http://arduino.ru/forum/proekty/meteostantsiya-dlya-narodnogo-monitoring... Ещё, очень часто в post запросе можно просить конкретную короткую инфу, к примеру курс валют не за год а за день или час. Тогда ответ короткий. Как это делать, нужно смотреть API сайта на который запрос уходит. Обычно в хэлпе сайта есть описание запросов (api). Удачи.

json, конечно, замечательно. Но!!!

Я запрашиваю обычный новостной сайт. Не отвечает он джисонами, ответ приходит в HTTP.

vitalikost
Offline
Зарегистрирован: 28.11.2014

Во кусок из проекта, думаю суть будет понятна:

  // Если есть доступные биты, читаем их и выводим на экран
String HTTP_req;
    if (client.available()) {
        Serial.println("Loading....."); 
        lcd.setCursor(0, 0);
        lcd.print("Loading.....");       // Выводим текст
        while (client.available()) {
           char c = client.read(); // read 1 byte (character) from client
          HTTP_req += c;  // save the HTTP request 1 char at a time              
        //  Serial.print(c); 
         delay(1);   
        }}

 

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

Ну так пример приведите. Я его тут же и проверю. Или... никак.

ну никак... значит никак. Это ж не мне нужно.

А для тех, кто все-таки хочет решить задачку - посоветую использовать функцию

WiFiClient * stream = https.getStreamPtr();

А к обьекту типа Stream уже можно обращаться, как. например, к Сериал - читать его побайтно и блоками любой длины, а не пытаться запихнуть весь ответ сервера в одну строку, на которую у вас не хвтает памяти

AlexTVR
Offline
Зарегистрирован: 06.10.2018

b707 пишет:

AlexTVR пишет:

Ну так пример приведите. Я его тут же и проверю. Или... никак.

ну никак... значит никак. Это ж не мне нужно.

А для тех, кто все-таки хочет решить задачку - посоветую использовать функцию

WiFiClient * stream = https.getStreamPtr();

А к обьекту типа Stream уже можно обращаться, как. например, к Сериал - читать его побайтно и блоками любой длины, а не пытаться запихнуть весь ответ сервера в одну строку, на которую у вас не хвтает памяти

"Берете массив char подходящей длины, например 200 символов.

Читаете из ответа сервера первые 200 символов, парсите... снова читаете 200 символов в ТОТ же массив...

В итоге вы можете прочитать ответ сервера хоть 10 мегабайт, имея один буфер 200 символов" - вот Ваши слова.

Не.... Задний ход не нужно включать. Пример приведите, как Вы будете читать 200 символов, потом снова 200 и т.д., теорию мы знаем. Тут теоретиков хоть отбавляй.

А 10 мегабайт где хранятся?

vitalikost
Offline
Зарегистрирован: 28.11.2014

AlexTVR пишет:

b707 пишет:

AlexTVR пишет:

Ну так пример приведите. Я его тут же и проверю. Или... никак.

ну никак... значит никак. Это ж не мне нужно.

А для тех, кто все-таки хочет решить задачку - посоветую использовать функцию

WiFiClient * stream = https.getStreamPtr();

А к обьекту типа Stream уже можно обращаться, как. например, к Сериал - читать его побайтно и блоками любой длины, а не пытаться запихнуть весь ответ сервера в одну строку, на которую у вас не хвтает памяти

"Берете массив char подходящей длины, например 200 символов.

Читаете из ответа сервера первые 200 символов, парсите... снова читаете 200 символов в ТОТ же массив...

В итоге вы можете прочитать ответ сервера хоть 10 мегабайт, имея один буфер 200 символов" - вот Ваши слова.

Не.... Задний ход не нужно включать. Пример приведите, как Вы будете читать 200 символов, потом снова 200 и т.д., теорию мы знаем. Тут теоретиков хоть отбавляй.

А 10 мегабайт где хранятся?

А зачем нам хранить 10 М? Если у нас есть ведро 10 литров с краником и крушка 200 гр. Что делаем когда крушка уже полна? 

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

Не.... Задний ход не нужно включать. Пример приведите, как Вы будете читать 200 символов

о господи...

вы даже не можете понять, что то что вы процитировали и мой ответ - это одно и то же :)

char char_buff[200];
  WiFiClient * stream = https.getStreamPtr();
  while (https.connected() ) {
    // запрашиваем оставшийся размер ответа 
    size_t size = stream->available();
    if (size) {
       // читаем очередные 200 байт, или, если в ответе меньше - все до конца
       int c = stream->readBytes(char_buff, ((size > sizeof(char_buff)) ? sizeof(char_buff) : size));
     if (c > 0)
     // обрабатываем буфер
   ....

и да, кстати - чтоб вы потом не возникали - я ничего этого сам не выдумывал,  в гугле примеров чтения ответов сервера по частям - полно, это абсолютно банальный и очевидный метод решения вашей задачи

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

b707 пишет:

AlexTVR пишет:

Не.... Задний ход не нужно включать. Пример приведите, как Вы будете читать 200 символов

это абсолютно банальный и очевидный метод решения вашей задачи

Если такой умный чего ты слона ел не по частям?

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Ссылка запроса секретная? Можно посмотреть какой ответ приходит?

b707
Offline
Зарегистрирован: 26.05.2017

p-a-h-a пишет:
Ссылка запроса секретная? Можно посмотреть какой ответ приходит?

да вряд ли вы от него ответ получите... этот товарищ уверен, что ему все вокруг должны, а сам он - никому... и даже когда он не по-детски тупит - виноват кто-то другой.

вот, ради интереса почитайте, с чего началось его общение на форуме (читать с 14 сообщения)

http://arduino.ru/forum/obshchii/oshibka-pri-zagruzke-sketcha-0

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Делал перерыв. Сейчас начну проверять. За ответы, конечно, спасибо!

sadman41
Offline
Зарегистрирован: 19.10.2016

На самом деле необязательно и 200 читать. Буфера должно хватать на одну самый длинный токен/лексему, а читать следует по байту. Токен распознал - буфер начал заполнять заново.

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Код не работает.

if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {       
                    
             Serial.println( https.getString().length());
             
             char char_buff[200];
             WiFiClient * stream = https.getStreamPtr();
             while (https.connected() ) { 
             Serial.println("******************");
 
Вот до этого сериала уже не доходит.
while (https.connected()  - нет TRUE.
 
Вот, что валит в сериал:
  6656
Wait 10s before next round...
[HTTPS] begin...
[HTTPS] GET...
[HTTPS] GET... code: 200
6656
Wait 10s before next round...
[HTTPS] begin...
[HTTPS] GET...
[HTTPS] GET... code: 200
6648
Wait 10s before next round...
[HTTPS] begin...
[HTTPS] GET...
[HTTPS] GET... code: 200
6656
Wait 10s before next round...
 
b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:
На самом деле необязательно и 200 читать. Буфера должно хватать на одну самый длинный токен/лексему, а читать следует по байту. Токен распознал - буфер начал заполнять заново.

ну это понятно, сколько надо - столько и читай

AlexTVR
Offline
Зарегистрирован: 06.10.2018

 Serial.println( https.getString().length()); - убрал это из кода и... началось чтение...

Дальше попробую сам.

Всем спасибо за решение проблемы!

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

 Serial.println( https.getString().length()); - убрал это из кода и... началось чтение...

конечно, ведь для того чтобы подсчитать длину строки - https.getString().length() - надо опять же сначала всю строку в память запихнуть

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Немного не понимаю.

Где хранится весь ответ с сайта после https.GET().? Все равно в памяти или пока сохраняется соединение - на сайте. А как долго оно сохраняется и успеет ли прочитать программа весь поток до разрыва соединения?

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

Все равно в памяти или ...где?

в буфере приемного модуля - сколько помещается. А как буфер заполнится - ЕСП дает команду удаленному серверу больше не слать. Когда вы начинаете выбирать данные - буфер постепенно освобождается и ЕСП запрашивает с сервера новые порции

А если вы используете строчку http.getString() - то вы даете команду приемнику получить сразу все. А оно не входит..

 

примерно так. Если где ошибся - Садман поправит.

b707
Offline
Зарегистрирован: 26.05.2017

AlexTVR пишет:

 как долго оно сохраняется и успеет ли прочитать программа весь поток до разрыва соединения?

есть такое понятие - таймаут. Если перерыв в приеме данных будет больше этой величины - сервер разорвет соединение. Конкретное значение зависит от настроек сервера и клиента.

Но в любом случае серевр не будет ждать часами :) Поэтому обрабатывать входящий поток надо быстро.

AlexTVR
Offline
Зарегистрирован: 06.10.2018

Спасибо! Теперь немного въехал. Я в этом деле новичок, получение информации с сайта HTTPS делаю впервые, поэтому столько вопросов.