ESP 32 не удалось подключиться к сайту https и вернуть данные с помощью GET
Я создал ThingHTTP ниже:
https://api.thingspeak.com/apps/thinghttp/send_request?api_key=BVLJ7A6KNK9VVAYK
В моем браузере я мог видеть ответ. Но я не могу заставить это работать в моем ESP32. Я понимаю, что это https, поэтому мне придется объявить данные корневого сертификата. Я попытался изменить на основе этого урока:
https://github.com/witnessmenow/arduino-sample-api-request/blob/master/ESP8266/HTTP_GET/HTTP_GET.ino
Мой код выглядит следующим образом:
#include <WiFi.h>
#include <WiFiClientSecure.h>
// - - - - - - - Замените следующее! ------
char ssid[] = "SSID"; // SSID вашей сети (имя)
char password[] = "pass"; // ваш сетевой пароль
// Для запросов, не связанных с HTTPS
// Уважаемый клиент;
// Для HTTPS-запросов
WiFiClientSecure client;
// Только база URL-адреса, к которому вы хотите подключиться
#define TEST_HOST "https://api.thingspeak.com/apps/thinghttp/send_request?api_key=BVLJ7A6KNK9VVAYK"
const char *server_cert = "-----BEGIN CERTIFICATE-----\n"
"MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n"
"RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n"
"VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n"
"DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n"
"ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n"
"VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n"
"mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n"
"IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n"
"mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n"
"XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n"
"dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n"
"jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n"
"BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n"
"DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n"
"9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n"
"jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n"
"Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n"
"ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n"
"R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n"
"-----END CERTIFICATE-----\n";
void setup() {
Serial.begin(115200);
// Connect to the WiFI
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
//--------
// Checking the cert is the best way on an ESP32
// This will verify the server is trusted.
client.setCACert(server_cert);
// If you don't want to verify the server
// Unlike the fingerprint method of the ESP8266 which expires frequently
// the cert lasts years, so I don't see much reason to ever
// use this on the ESP32
// client.setInsecure();
makeHTTPRequest();
}
void makeHTTPRequest() {
delay(5000);
// Opening connection to server (Use 80 as port if HTTP)
if (!client.connect(TEST_HOST, 443))
{
Serial.println(F("Connection failed"));
return;
}
// give the esp a breather
yield();
client.connect(TEST_HOST, 443);
// Send HTTP request
client.print(F("GET "));
// This is the second half of a request (everything that comes after the base URL)
client.print(""); // %2C == ,
client.println(F(" HTTP/1.1"));
//Headers
client.print(F("Host: "));
client.println(TEST_HOST);
client.println(F("Cache-Control: no-cache"));
if (client.println() == 0)
{
Serial.println(F("Failed to send request"));
return;
}
//delay(100);
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0)
{
Serial.print(F("Unexpected response: "));
Serial.println(status);
return;
}
// Skip HTTP headers
char endOfHeaders[] = "\r\n\r\n";
if (!client.find(endOfHeaders))
{
Serial.println(F("Invalid response"));
return;
}
// This is probably not needed for most, but I had issues
// with the Tindie api where sometimes there were random
// characters coming back before the body of the response.
// This will cause no hard to leave it in
// peek() will look at the character, but not take it off the queue
while (client.available() && client.peek() != '{')
{
char c = 0;
client.readBytes(&c, 1);
Serial.print(c);
Serial.println("BAD");
}
// While the client is still availble read each
// byte and print to the serial monitor
while (client.available()) {
char c = 0;
client.readBytes(&c, 1);
Serial.print(c);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
программа смогла скомпилироваться и могла работать до тех пор, пока не будет показано, что она подключена к сети. Но затем он вернул "Соединение не удалось!" Я полагаю, что он застрял на этой строке :
if (!client.connect(TEST_HOST, 443))
Я не уверен, в чем здесь проблема. Комментарии приветствуются.
@sam, 👍0
Обсуждение2 ответа
Лучший ответ:
Что - то не так с вашим запросом GET (которые не имеют ничего общего с Arduino-просто изучите основы протокола, который вы пытаетесь использовать, прежде чем использовать его):
- Вы пытаетесь открыть сокет по URL-адресу, а не по серверу. Это никогда не сработает. Вместо этого подключитесь к серверу (подсказка: сервер или "ПОЛНОЕ доменное имя" - это бит между
https://
и следующим/
). - Вы не указываете никакого пути в своем
запросе GET, только комментарий, в котором говорится, что вы должны предоставить. Подсказка: путь-это все, что следует после (и включая)
/
после полного доменного имени. - Ваш
заголовок Host: должен содержать только полное доменное имя, а не весь URL-адрес. К настоящему времени вы уже должны знать, что такое полное доменное имя.
- Вы также должны включить
соединение: закройте
в заголовках, чтобы сообщить серверу, что вы не будете держать сокет открытым.
Исправьте эти проблемы, и вы, возможно, начнете видеть, как происходит что-то полезное.
Спасибо за советы. Был новичком в этом деле. Наверное, я начал не с того места. Во всяком случае, после реализации того, что вы сказали, и других незначительных ошибок, похоже, это работает. Я узнал, что мне нужно изменить сертификаты для веб-сайта, их несколько типов. В любом случае, еще раз спасибо., @sam
Приведенный ниже фрагмент кода взят из кода прошивки, которую я недавно программировал для использования на микроконтроллерах Tensilica, совместимых с Xtensa LX6/7 (ESP32). В приведенном ниже коде выполняется HTTPS-запрос с использованием библиотеки WIFIClientsecure.
String GetInfoFromDataverse(String url) {
//Проверяем статус соединения WiFi
if(WiFi.status() != WL_CONNECTED){
mserial.printStrln("WiFi Disconnected");
if (connect2WIFInetowrk()){
GetInfoFromDataverse(url);
}
}
int str_len = SERVER_URL.length() + 1; // Длина (с одним дополнительным символом нулевого терминатора)
char SERVER_URL_char [str_len]; // Подготавливаем массив символов (буфер)
SERVER_URL.toCharArray(SERVER_URL_char, str_len); // Копируем его
client.stop();
client.setCACert(HARVARD_ROOT_CA_RSA_SHA1);
if (!client.connect(SERVER_URL_char, SERVER_PORT)) {
mserial.printStrln("Cloud server URL connection FAILED!");
mserial.printStrln(SERVER_URL_char);
int server_status = client.connected();
mserial.printStrln("Server status code: " + String(server_status));
return "";
}
mserial.printStrln("Connected to the dataverse of Harvard University");
mserial.printStrln("");
// Теперь мы создаем URI для запроса
mserial.printStr("Requesting URL: ");
mserial.printStrln(url);
// Делаем HTTP-запрос и добавляем HTTP-заголовки
// заголовок сообщения
String postHeader = "GET https://" + SERVER_URL + URL + " HTTP/1.1\r\n";
postHeader += "Host: " + SERVER_URL + ":" + String(SERVER_PORT) + "\r\n";
//postHeader += "X-Dataverse-key: " + API_TOKEN + "\r\n";
postHeader += "Content-Type: text/json\r\n";
postHeader += "Accept: text/html,application/xhtml+xml,application/xml,application/json,text/json;q=0.9,*/*;q=0.8\r\n";
postHeader += "Accept-Encoding: gzip,deflate\r\n";
postHeader += "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n";
postHeader += "User-Agent: AeonLabs LDAD Smart DAQ device\r\n";
postHeader += "Keep-Alive: 300\r\n";
postHeader += "Connection: keep-alive\r\n";
postHeader += "Accept-Language: en-us\r\n";
// хвост запроса
String tail = "\r\n--" + boundary + "--\r\n\r\n";
// длина содержимого
int contentLength = tail.length();
postHeader += "Content-Length: " + String(contentLength, DEC) + "\n\n";
// отправляем заголовок поста
int postHeader_len=postHeader.length() + 1;
char charBuf0[postHeader_len];
postHeader.toCharArray(charBuf0, postHeader_len);
client.print(charBuf0);
mserial.printStrln("======= Headers =======");
mserial.printStrln(charBuf0);
mserial.printStrln("======= End of Headers =======");
// Читаем все строки ответа с сервера и печатаем их в mserial
String responseHeaders = "";
mserial.printStr("Waiting for server response...");
long timeout= millis();
long ttl=millis()-timeout;
while (client.connected() && abs(ttl) < 30000) { // 30 сек.
ttl=millis()-timeout;
responseHeaders = client.readStringUntil('\n');
if (responseHeaders == "\r") {
break;
}
}
if (abs(ttl) < 30000){
mserial.printStrln("OK");
}else{
mserial.printStrln("timed out.");
}
String responseContent = client.readStringUntil('\n');
client.stop();
return responseContent;
}
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Как выбрать альтернативные контакты I2C на ESP32?
- Драйверы для чипа последовательного порта CH9102X
- Как преобразовать форматированный оператор print в строковую переменную?
- ESP32 - "Детектор Браунаута был активирован" при запуске Wi-Fi
- Питание esp32cam от аккумулятора
- Контакты RX и TX на esp32
- ESP32: отключить детектор отключения питания
Попробуйте создать правильно отформатированный HTTP-запрос. Попробуйте также подключиться к серверу, а не к веб-странице. В вашем запросе на получение так много ошибок, что я не знаю, с чего начать..., @Majenko