使用 HttpsOTAUpdate 从 GCS 下载二进制文件
Download binary from GCS using HttpsOTAUpdate
所以我正在尝试从 GCS(google 云存储)存储桶下载二进制文件,以使用以下支持的结构更新 esp32
的固件:
代码如下所示
// This sketch provide the functionality of OTA Firmware Upgrade
#include "WiFi.h"
#include "HttpsOTAUpdate.h"
// This sketch shows how to implement HTTPS firmware update Over The Air.
// Please provide your WiFi credentials, https URL to the firmware image and the server certificate.
static const char *ssid = "ssid"; // your network SSID (name of wifi network)
static const char *password = "psswd"; // your network password
static const char *url = "https://storage.googleapis.com/bucket/firmware.bin"; // state url of your firmware image
static const char *server_certificate = "-----BEGIN CERTIFICATE-----\n"
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
"-----END CERTIFICATE-----";
static HttpsOTAStatus_t otastatus;
void HttpEvent(HttpEvent_t *event)
{
switch (event->event_id)
{
case HTTP_EVENT_ERROR:
Serial.println("Http Event Error");
break;
case HTTP_EVENT_ON_CONNECTED:
Serial.println("Http Event On Connected");
break;
case HTTP_EVENT_HEADER_SENT:
Serial.println("Http Event Header Sent");
break;
case HTTP_EVENT_ON_HEADER:
Serial.printf("Http Event On Header, key=%s, value=%s\n", event->header_key, event->header_value);
break;
case HTTP_EVENT_ON_DATA:
break;
case HTTP_EVENT_ON_FINISH:
Serial.println("Http Event On Finish");
break;
case HTTP_EVENT_DISCONNECTED:
Serial.println("Http Event Disconnected");
break;
}
}
void setup()
{
Serial.begin(115200);
Serial.print("Attempting to connect to SSID: ");
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
HttpsOTA.onHttpEvent(HttpEvent);
Serial.println("Starting OTA");
HttpsOTA.begin(url, server_certificate);
Serial.println("Please Wait it takes some time ...");
}
void loop()
{
otastatus = HttpsOTA.status();
if (otastatus == HTTPS_OTA_SUCCESS)
{
Serial.println("Firmware written successfully. To reboot device, call API ESP.restart() or PUSH restart button on device");
}
else if (otastatus == HTTPS_OTA_FAIL)
{
Serial.println("Firmware Upgrade Fail");
}
delay(1000);
}
我收到以下错误:
Starting OTA
Please Wait it takes some time ...
E (1547) esp-tls: mbedtls_ssl_handshake returned -0x2700
E (1549) esp-tls: Failed to open new connection
E (1549) TRANS_SSL: Failed to open a new connection
E (1550) HTTP_CLIENT: Connection failed, sock < 0
E (1554) esp_https_ota: Failed to open HTTP connection: ESP_ERR_HTTP_CONNECT
E (1561) esp_https_ota: Failed to establish HTTP connection
Http Event Disconnected
Http Event Disconnected
Firmware Upgrade Fail
Firmware Upgrade Fail
Firmware Upgrade Fail
我相信这与请求中用于 TLS 的证书有关。
问题是,我如何find/generate正确的证书与 GCS 通信?
从存储桶下载内容需要对您的客户端进行身份验证。您不能只将 HTTPS 客户端指向存储桶 URL 并愉快地下载。您需要先生成一个 OAuth2 令牌,然后将其包含在您请求的 header 中:
https://cloud.google.com/storage/docs/downloading-objects#rest-download-object
I believe this is associated to the certificate used for TLS in the request.
Yes, this may be the problem.
您示例中的 server_certificate
是 Let's Encrypt Authority 证书(C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3),但要建立连接,您可能需要服务器叶证书。
您可以使用 OpenSSL 获取它。如果您要连接到 https://storage.googleapis.com/bucket/firmware.bin,则命令将如下所示:
openssl s_client -showcerts -servername storage.googleapis.com -connect storage.googleapis.com:443 </dev/null
输出中会有多个证书,您需要复制第一个并将其放在 Let's Encrypt 中。
所以我正在尝试从 GCS(google 云存储)存储桶下载二进制文件,以使用以下支持的结构更新 esp32
的固件:
代码如下所示
// This sketch provide the functionality of OTA Firmware Upgrade
#include "WiFi.h"
#include "HttpsOTAUpdate.h"
// This sketch shows how to implement HTTPS firmware update Over The Air.
// Please provide your WiFi credentials, https URL to the firmware image and the server certificate.
static const char *ssid = "ssid"; // your network SSID (name of wifi network)
static const char *password = "psswd"; // your network password
static const char *url = "https://storage.googleapis.com/bucket/firmware.bin"; // state url of your firmware image
static const char *server_certificate = "-----BEGIN CERTIFICATE-----\n"
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n"
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n"
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n"
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n"
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n"
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n"
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n"
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n"
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n"
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n"
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n"
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n"
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n"
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n"
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n"
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n"
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n"
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n"
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n"
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n"
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n"
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n"
"-----END CERTIFICATE-----";
static HttpsOTAStatus_t otastatus;
void HttpEvent(HttpEvent_t *event)
{
switch (event->event_id)
{
case HTTP_EVENT_ERROR:
Serial.println("Http Event Error");
break;
case HTTP_EVENT_ON_CONNECTED:
Serial.println("Http Event On Connected");
break;
case HTTP_EVENT_HEADER_SENT:
Serial.println("Http Event Header Sent");
break;
case HTTP_EVENT_ON_HEADER:
Serial.printf("Http Event On Header, key=%s, value=%s\n", event->header_key, event->header_value);
break;
case HTTP_EVENT_ON_DATA:
break;
case HTTP_EVENT_ON_FINISH:
Serial.println("Http Event On Finish");
break;
case HTTP_EVENT_DISCONNECTED:
Serial.println("Http Event Disconnected");
break;
}
}
void setup()
{
Serial.begin(115200);
Serial.print("Attempting to connect to SSID: ");
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
HttpsOTA.onHttpEvent(HttpEvent);
Serial.println("Starting OTA");
HttpsOTA.begin(url, server_certificate);
Serial.println("Please Wait it takes some time ...");
}
void loop()
{
otastatus = HttpsOTA.status();
if (otastatus == HTTPS_OTA_SUCCESS)
{
Serial.println("Firmware written successfully. To reboot device, call API ESP.restart() or PUSH restart button on device");
}
else if (otastatus == HTTPS_OTA_FAIL)
{
Serial.println("Firmware Upgrade Fail");
}
delay(1000);
}
我收到以下错误:
Starting OTA
Please Wait it takes some time ...
E (1547) esp-tls: mbedtls_ssl_handshake returned -0x2700
E (1549) esp-tls: Failed to open new connection
E (1549) TRANS_SSL: Failed to open a new connection
E (1550) HTTP_CLIENT: Connection failed, sock < 0
E (1554) esp_https_ota: Failed to open HTTP connection: ESP_ERR_HTTP_CONNECT
E (1561) esp_https_ota: Failed to establish HTTP connection
Http Event Disconnected
Http Event Disconnected
Firmware Upgrade Fail
Firmware Upgrade Fail
Firmware Upgrade Fail
我相信这与请求中用于 TLS 的证书有关。
问题是,我如何find/generate正确的证书与 GCS 通信?
从存储桶下载内容需要对您的客户端进行身份验证。您不能只将 HTTPS 客户端指向存储桶 URL 并愉快地下载。您需要先生成一个 OAuth2 令牌,然后将其包含在您请求的 header 中:
https://cloud.google.com/storage/docs/downloading-objects#rest-download-object
I believe this is associated to the certificate used for TLS in the request. Yes, this may be the problem.
您示例中的 server_certificate
是 Let's Encrypt Authority 证书(C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3),但要建立连接,您可能需要服务器叶证书。
您可以使用 OpenSSL 获取它。如果您要连接到 https://storage.googleapis.com/bucket/firmware.bin,则命令将如下所示:
openssl s_client -showcerts -servername storage.googleapis.com -connect storage.googleapis.com:443 </dev/null
输出中会有多个证书,您需要复制第一个并将其放在 Let's Encrypt 中。