Aggiornamenti OTA su ESP32 tramite browser web: caricamento in HTTPS (SSL/TLS) con certificato autofirmato – 2
In questo articolo, esploreremo come eseguire gli aggiornamenti OTA su ESP32 utilizzando un browser Web e un protocollo HTTPS con un certificato autofirmato. HTTPS fornisce un modo sicuro per trasferire i dati su Internet ed è essenziale per qualsiasi processo di aggiornamento OTA che coinvolge informazioni sensibili. Un certificato autofirmato può essere utilizzato per fornire crittografia e autenticazione senza la necessità di un’autorità di certificazione di terze parti, rendendolo una soluzione conveniente per progetti su piccola scala.
Inizieremo configurando ESP32 per gli aggiornamenti OTA, quindi genereremo un certificato autofirmato e configureremo il server HTTPS. Infine, testeremo il processo di aggiornamento OTA caricando una nuova versione del firmware utilizzando un browser web. Entro la fine di questo articolo, avrai un processo di aggiornamento OTA funzionante per il tuo progetto ESP32 che utilizza il protocollo HTTPS e un certificato autofirmato.
L’aggiornamento OTA (Over the Air) è il processo di caricamento del firmware su un modulo ESP32 utilizzando una connessione Wi-Fi anziché una porta seriale. Tale funzionalità diventa estremamente utile in caso di accesso fisico limitato o nullo al modulo.
Gli aggiornamenti OTA possono essere effettuati con le seguenti modalità:
- IDE Arduino
- Programma di navigazione in rete
- Server HTTP
Prima di tutto, controlla il tutorial “ESP32: flash del firmware binario compilato (.bin)“.
Introduzione
nnanzitutto, osserviamo che il componente principale di ESP32 core ha bisogno di python installato e, durante l’installazione, ricordati di aggiungerlo alla PATH (per Windows)
Quindi vai a leggere come creare un file binario da questo articolo “ESP32: flash del firmware binario compilato (.bin)“.
Aggiornamento del firmware crittografato SSL/TLS protetto da password
Innanzitutto, penso che in questo caso non abbia senso utilizzare un certificato autofirmato perché se lo si desidera utilizzare internamente (nella rete LAN privata), non si aggiunge un certificato, si è già all’interno di una rete sicura e se vuoi esportare su Internet, una soluzione migliore è utilizzare un proxy con un singolo punto di ingresso con un certificato completo (come myhostname.org) e un set di endpoint che puntano al dispositivo.
Generare il certificato autofirmato
Se si desidera utilizzare un certificato autofirmato, è possibile utilizzare OpenSSL per la generazione delle chiavi private e del certificato.
Puoi ottenere openssl scaricando la versione Linux da tutti i gestori di pacchetti, oppure scaricarlo per Windows da qui , per usarlo con più semplicità aggiungi l’eseguibile alla path.
openssl req -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout key.pem -days 365 -out cert.pem -subj "/CN=esp32-webupdate.local"
ed ecco la risposta
Generating a RSA private key
................................+++++
..........................................................+++++
writing new private key to 'key.pem'
-----
Ecco il contenuto del key.pem
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDHgkVGDdBv32Ba
MCgjTyw/dolIeix2YxsBPIvWVNqjq3nTwjGXrXUcr8Z2kJ7NVTXE3UVkHnMZmPeU
m4Gii9z5UbLk8tPhd1ZpQOKPZdioTFAZ6qKxspm4xVJqIW+gBRY849ofkP6DcDec
6dCYj8eJdQgARSfggDHL+Oc+0qh9YEZkRjyYIZWl3R5uVEi51AF5s7rWstuhvIUa
P/kSvvyIB1RRH4sgi8ARpY4uv9v/8EklRuh+eSYxz0U4aYcIqjSHBiG2U3utncxz
wKyz/T4G7Fbp1LAJhJqzPN2N1DznM6gFLlXvHJk8c4sJCHJpd7rgOvJEfte1xTuP
XKE1YNX3AgMBAAECggEACXMCFO9Sj/nkdmERhZqaXecfWW9v66uF++kCNoSOVnIo
sv7fmm98vH8Wx0bSPqdqhIh2YOeQTAYSs9cprKkzLhvQfUeDAYrFbPbFxETungn/
QTr7ua7b2QR/gsdSoiGbjAa+rgAQDemiuKvaVV958+i3GEwuN1PbB+4iBbe0gzuW
jUNjyHLw6TqlmnSS6Vf6JiKJU0czIjWW5lwJE30iyJp03LGbZDCmvyWGqN3zdW8y
PwI8GgrWHX2sgttWfWLlCZV0D582cWLc0ZKEkRyAOuhkUJ8Y/MwUKj/M/frB3Ii+
eEdhKNLUYlQY/Nh3QHL3ohjnzQ7/O+dLRf+6gBYgAQKBgQD9hhD4mt8NYuKRDnu5
4douvEmKLN18hJANFJjkDwQzRJsVnaGIEEJVZ7LpDwTy5+lNw+lvn3D5AVB++f+8
cXkwDIcEZbwk+/eOWz3SEPo1KwGhs8EQM7IzfRlXrkUsXMvu8Up4paueU4W5Pf7c
yXgnNbs0Fu9l90D/mV7OiNR/dwKBgQDJdSQGT9bfq5et8XsVnQQXg6BWc6/k75aa
qlvpgeXQtSKOmzTEkJz34Fu7sIEm1dQ0RUjDEz5EQVZcog34Dn/+K8aRBRrMFn17
wCdL0m3PgXlJlM42m1eaJ0vVO0p1jCtvGK+fP+AORz1hjOWeIHmhw4bYE+1w2F6x
oKFpH0z9gQKBgQCLJ39BNaCgtFovzIdU7AbaCDdFRIL9ybVXuKqC40sm6M1G/BKh
oGsIfbbR/ZB1051XNeV3g0h7JKGOUKJySMZ//SBO5ZhzpGmpFaPFHdR4QnbOzt91
iSqS4GN8oQcO5pB5Qq/hsO2WJboMh17QyTTOMMvkN4KHsUNYCFLlgm1A2QKBgQCS
7ov6yopmkilLpX9nMSEF4Wu1AiV87T3DypLEyYgLY8Ezj4G6B9tkcs+VIdPgtj5S
bWH3XXaho6HQaCWWEUVK5TSrGrUDuzeEZY6Dn5OVr9H9V7nbXAtVlGmbuOXCvBwF
qFSW6qiI4W6kUnY6kWcFE62qtUYNctIF7aksGbc2gQKBgQDK9tuP4pR1WBcK4kDa
r7EYWs5G83ceXVCTMf0XFJPgwNm0RduJ/ntRSWTj2jc5rENMEiFQpMIKz1h/rKkx
c/m7ZT9AbedAUxXOm9a/LKaTsJ11R/XO1MQE3QDZIDIq7C9Osd2Ap2WXdPazCtRR
D9eczO3iHYoTPvDYNWxDf45oig==
-----END PRIVATE KEY-----
e cert.pem
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIUdZdm1T/ibN+bQ5JB0+c+rnFPOZcwDQYJKoZIhvcNAQEL
BQAwIDEeMBwGA1UEAwwVZXNwMzItd2VidXBkYXRlLmxvY2FsMB4XDTIxMDkyNDEw
MjUwMloXDTIyMDkyNDEwMjUwMlowIDEeMBwGA1UEAwwVZXNwMzItd2VidXBkYXRl
LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx4JFRg3Qb99g
WjAoI08sP3aJSHosdmMbATyL1lTao6t508Ixl611HK/GdpCezVU1xN1FZB5zGZj3
lJuBoovc+VGy5PLT4XdWaUDij2XYqExQGeqisbKZuMVSaiFvoAUWPOPaH5D+g3A3
nOnQmI/HiXUIAEUn4IAxy/jnPtKofWBGZEY8mCGVpd0eblRIudQBebO61rLbobyF
Gj/5Er78iAdUUR+LIIvAEaWOLr/b//BJJUbofnkmMc9FOGmHCKo0hwYhtlN7rZ3M
c8Css/0+BuxW6dSwCYSaszzdjdQ85zOoBS5V7xyZPHOLCQhyaXe64DryRH7XtcU7
j1yhNWDV9wIDAQABo1MwUTAdBgNVHQ4EFgQULJvBhUDPFKnnSkWxNSH24EVWZbgw
HwYDVR0jBBgwFoAULJvBhUDPFKnnSkWxNSH24EVWZbgwDwYDVR0TAQH/BAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAQEAVc6IOt7zUDmy4sX2hcKnhzmpi5O9M0MqL9wx
46ocbTbFZfc5MecyyKQJ7vEk013f+tD9Vdj/OFBXXyffkBEe0JU5cpbzPMZb22Nu
24dP1hGt/kdsJEbXg3ZUGJbpJgfmF7mgMn6vp0ggp1Yprn3794Xh+QtnaVLnfGIc
dPH4qMLclwoZyA6xKeJjaGz6zQcHITzA6Eb9xX+HJKn91AOEJluUB+RubJBQlNpC
BeI1DvXhssiknKx4e/axcbbRxsW7VBeSK+5CR6y8yTHFJqXPJ0JWkby0NOi6C4es
UhplRTTHcxfOONyYWUIHas659U9yrEu8t8sTOyNQZPJ2ckdW5A==
-----END CERTIFICATE-----
Convertilo in bytearray
SSLCert ha bisogno del certificato e della chiave in formato bytearray
// Create an SSL certificate object from the files above
SSLCert cert = SSLCert(
(unsigned char *)cert_pem, cert_pem_len,
(unsigned char *)key_pem, key_pem_len
);
puoi usare il mio convertitore online per convertire.
Sketch di esempio HTTPS
Ottenere la libreria per il server HTTPS
Per eseguire questo esempio, hai bisogno di una libreria esterna che puoi trovare qui su GitHub .
Puoi SCARICARE il file zip della libreria, quindi estrarre il contenuto e copiarlo in formato <sketchbook location>\libraries
.
Sketch di esempio
Ora aggiungiamo i certificati al codice di esempio
/**
* Example for the ESP32 HTTP(S) OTA Update Webserver
*
* Check the guide to how to generate key and cert
* and convert in bytearray with this tool
* https://mischianti.org/online-converter-file-to-cpp-gzip-byte-array-3/
*
* Renzo Mischianti <www.mischianti.org>
*
* https://mischianti.org/
*
*/
#define WIFI_SSID "<YOUR-SSID>"
#define WIFI_PSK "<YOUR-PASSWD>"
// We will use wifi
#include <WiFi.h>
// Includes for the server
#include <HTTPSServer.hpp>
#include <SSLCert.hpp>
#include <HTTPRequest.hpp>
#include <HTTPResponse.hpp>
#include <HTTPBodyParser.hpp>
#include <HTTPMultipartBodyParser.hpp>
#include <HTTPURLEncodedBodyParser.hpp>
#include <Update.h>
#include <SPIFFS.h>
//File: cert.pem, Size: 1170
#define cert_pem_len 1170
const uint8_t cert_pem[] PROGMEM = {
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0A, 0x4D, 0x49, 0x49,
0x44, 0x4A, 0x54, 0x43, 0x43, 0x41, 0x67, 0x32, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49,
0x55, 0x49, 0x62, 0x54, 0x73, 0x6D, 0x66, 0x2F, 0x50, 0x55, 0x4C, 0x4C, 0x70, 0x75, 0x75, 0x51,
0x50, 0x41, 0x77, 0x61, 0x39, 0x7A, 0x30, 0x32, 0x79, 0x79, 0x78, 0x41, 0x77, 0x44, 0x51, 0x59,
0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x0D, 0x0A, 0x42,
0x51, 0x41, 0x77, 0x49, 0x6A, 0x45, 0x67, 0x4D, 0x42, 0x34, 0x47, 0x41, 0x31, 0x55, 0x45, 0x41,
0x77, 0x77, 0x58, 0x5A, 0x58, 0x4E, 0x77, 0x4F, 0x44, 0x49, 0x32, 0x4E, 0x69, 0x31, 0x33, 0x5A,
0x57, 0x4A, 0x31, 0x63, 0x47, 0x52, 0x68, 0x64, 0x47, 0x55, 0x75, 0x62, 0x47, 0x39, 0x6A, 0x59,
0x57, 0x77, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x45, 0x77, 0x4F, 0x54, 0x41, 0x32, 0x0D,
0x0A, 0x4D, 0x54, 0x55, 0x7A, 0x4F, 0x54, 0x55, 0x33, 0x57, 0x68, 0x63, 0x4E, 0x4D, 0x6A, 0x49,
0x77, 0x4F, 0x54, 0x41, 0x32, 0x4D, 0x54, 0x55, 0x7A, 0x4F, 0x54, 0x55, 0x33, 0x57, 0x6A, 0x41,
0x69, 0x4D, 0x53, 0x41, 0x77, 0x48, 0x67, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x44, 0x42, 0x64,
0x6C, 0x63, 0x33, 0x41, 0x34, 0x4D, 0x6A, 0x59, 0x32, 0x4C, 0x58, 0x64, 0x6C, 0x59, 0x6E, 0x56,
0x77, 0x0D, 0x0A, 0x5A, 0x47, 0x46, 0x30, 0x5A, 0x53, 0x35, 0x73, 0x62, 0x32, 0x4E, 0x68, 0x62,
0x44, 0x43, 0x43, 0x41, 0x53, 0x49, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B, 0x6F, 0x5A, 0x49, 0x68,
0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x42, 0x42, 0x51, 0x41, 0x44, 0x67, 0x67, 0x45, 0x50, 0x41,
0x44, 0x43, 0x43, 0x41, 0x51, 0x6F, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4D, 0x64, 0x35, 0x4A,
0x51, 0x72, 0x55, 0x0D, 0x0A, 0x4E, 0x61, 0x43, 0x79, 0x43, 0x72, 0x66, 0x57, 0x72, 0x56, 0x30,
0x56, 0x50, 0x58, 0x6D, 0x37, 0x63, 0x31, 0x59, 0x67, 0x6F, 0x56, 0x49, 0x75, 0x58, 0x57, 0x37,
0x4C, 0x72, 0x74, 0x4D, 0x67, 0x4B, 0x33, 0x33, 0x5A, 0x62, 0x78, 0x64, 0x4F, 0x6F, 0x4B, 0x49,
0x4E, 0x63, 0x2B, 0x61, 0x72, 0x78, 0x54, 0x4E, 0x6C, 0x68, 0x41, 0x67, 0x39, 0x53, 0x32, 0x50,
0x6A, 0x32, 0x52, 0x65, 0x59, 0x0D, 0x0A, 0x35, 0x4B, 0x67, 0x32, 0x61, 0x67, 0x70, 0x37, 0x39,
0x70, 0x64, 0x30, 0x2B, 0x2F, 0x76, 0x57, 0x34, 0x54, 0x69, 0x47, 0x6F, 0x6E, 0x39, 0x6B, 0x37,
0x42, 0x45, 0x55, 0x38, 0x65, 0x77, 0x64, 0x44, 0x44, 0x4F, 0x38, 0x64, 0x65, 0x37, 0x4A, 0x52,
0x62, 0x63, 0x32, 0x30, 0x56, 0x49, 0x38, 0x42, 0x52, 0x33, 0x72, 0x51, 0x52, 0x61, 0x6C, 0x75,
0x6F, 0x70, 0x35, 0x5A, 0x79, 0x44, 0x43, 0x0D, 0x0A, 0x62, 0x4D, 0x48, 0x63, 0x4B, 0x5A, 0x56,
0x61, 0x39, 0x58, 0x71, 0x68, 0x32, 0x57, 0x4A, 0x45, 0x47, 0x73, 0x6C, 0x75, 0x57, 0x70, 0x56,
0x79, 0x67, 0x74, 0x4E, 0x6A, 0x5A, 0x41, 0x73, 0x62, 0x55, 0x56, 0x69, 0x34, 0x32, 0x6A, 0x48,
0x32, 0x69, 0x70, 0x6F, 0x74, 0x53, 0x69, 0x68, 0x65, 0x56, 0x79, 0x31, 0x68, 0x68, 0x56, 0x4A,
0x75, 0x63, 0x63, 0x52, 0x43, 0x55, 0x4D, 0x6A, 0x75, 0x0D, 0x0A, 0x72, 0x6B, 0x42, 0x76, 0x35,
0x55, 0x45, 0x5A, 0x6D, 0x73, 0x33, 0x6B, 0x55, 0x42, 0x47, 0x68, 0x41, 0x7A, 0x66, 0x74, 0x48,
0x48, 0x31, 0x63, 0x31, 0x6D, 0x70, 0x58, 0x34, 0x41, 0x7A, 0x51, 0x5A, 0x4F, 0x75, 0x78, 0x32,
0x53, 0x65, 0x6A, 0x4F, 0x57, 0x4D, 0x64, 0x65, 0x75, 0x42, 0x4D, 0x30, 0x53, 0x68, 0x58, 0x30,
0x53, 0x78, 0x39, 0x46, 0x31, 0x64, 0x73, 0x37, 0x51, 0x61, 0x4E, 0x0D, 0x0A, 0x44, 0x56, 0x54,
0x73, 0x42, 0x74, 0x67, 0x77, 0x67, 0x75, 0x4A, 0x6F, 0x4C, 0x48, 0x36, 0x31, 0x64, 0x56, 0x63,
0x4A, 0x34, 0x33, 0x5A, 0x65, 0x53, 0x47, 0x65, 0x37, 0x4E, 0x39, 0x71, 0x57, 0x71, 0x50, 0x74,
0x5A, 0x53, 0x48, 0x2B, 0x4F, 0x52, 0x50, 0x64, 0x4C, 0x2F, 0x6D, 0x4B, 0x2F, 0x58, 0x78, 0x4D,
0x6C, 0x71, 0x71, 0x54, 0x75, 0x6A, 0x53, 0x48, 0x34, 0x61, 0x64, 0x31, 0x71, 0x0D, 0x0A, 0x36,
0x70, 0x62, 0x62, 0x77, 0x49, 0x43, 0x54, 0x36, 0x4B, 0x31, 0x57, 0x54, 0x51, 0x30, 0x43, 0x41,
0x77, 0x45, 0x41, 0x41, 0x61, 0x4E, 0x54, 0x4D, 0x46, 0x45, 0x77, 0x48, 0x51, 0x59, 0x44, 0x56,
0x52, 0x30, 0x4F, 0x42, 0x42, 0x59, 0x45, 0x46, 0x48, 0x59, 0x35, 0x37, 0x74, 0x63, 0x56, 0x6A,
0x54, 0x51, 0x70, 0x35, 0x74, 0x69, 0x70, 0x57, 0x66, 0x67, 0x51, 0x54, 0x31, 0x70, 0x65, 0x0D,
0x0A, 0x45, 0x72, 0x45, 0x5A, 0x4D, 0x42, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x49, 0x77, 0x51,
0x59, 0x4D, 0x42, 0x61, 0x41, 0x46, 0x48, 0x59, 0x35, 0x37, 0x74, 0x63, 0x56, 0x6A, 0x54, 0x51,
0x70, 0x35, 0x74, 0x69, 0x70, 0x57, 0x66, 0x67, 0x51, 0x54, 0x31, 0x70, 0x65, 0x45, 0x72, 0x45,
0x5A, 0x4D, 0x41, 0x38, 0x47, 0x41, 0x31, 0x55, 0x64, 0x45, 0x77, 0x45, 0x42, 0x2F, 0x77, 0x51,
0x46, 0x0D, 0x0A, 0x4D, 0x41, 0x4D, 0x42, 0x41, 0x66, 0x38, 0x77, 0x44, 0x51, 0x59, 0x4A, 0x4B,
0x6F, 0x5A, 0x49, 0x68, 0x76, 0x63, 0x4E, 0x41, 0x51, 0x45, 0x4C, 0x42, 0x51, 0x41, 0x44, 0x67,
0x67, 0x45, 0x42, 0x41, 0x49, 0x38, 0x32, 0x6F, 0x44, 0x32, 0x41, 0x36, 0x4D, 0x51, 0x48, 0x78,
0x78, 0x79, 0x35, 0x39, 0x31, 0x58, 0x36, 0x56, 0x52, 0x2F, 0x45, 0x49, 0x58, 0x39, 0x72, 0x57,
0x46, 0x32, 0x54, 0x0D, 0x0A, 0x58, 0x68, 0x65, 0x6E, 0x34, 0x49, 0x6D, 0x53, 0x79, 0x6D, 0x71,
0x6D, 0x35, 0x56, 0x46, 0x73, 0x51, 0x44, 0x41, 0x71, 0x52, 0x4C, 0x70, 0x62, 0x42, 0x71, 0x57,
0x4F, 0x36, 0x74, 0x30, 0x42, 0x67, 0x69, 0x41, 0x66, 0x62, 0x51, 0x4E, 0x47, 0x37, 0x6C, 0x33,
0x6B, 0x6B, 0x58, 0x51, 0x78, 0x41, 0x33, 0x73, 0x42, 0x2B, 0x6C, 0x49, 0x5A, 0x67, 0x4A, 0x65,
0x76, 0x67, 0x52, 0x4B, 0x74, 0x0D, 0x0A, 0x65, 0x37, 0x74, 0x65, 0x79, 0x31, 0x48, 0x7A, 0x64,
0x59, 0x75, 0x50, 0x76, 0x46, 0x46, 0x42, 0x65, 0x31, 0x58, 0x6F, 0x54, 0x38, 0x72, 0x52, 0x2F,
0x6C, 0x7A, 0x2B, 0x41, 0x63, 0x74, 0x51, 0x54, 0x67, 0x49, 0x61, 0x46, 0x42, 0x4E, 0x50, 0x45,
0x66, 0x74, 0x6F, 0x57, 0x65, 0x55, 0x70, 0x4F, 0x4B, 0x4A, 0x48, 0x58, 0x5A, 0x37, 0x4E, 0x61,
0x57, 0x69, 0x41, 0x76, 0x6D, 0x70, 0x43, 0x0D, 0x0A, 0x6A, 0x69, 0x7A, 0x78, 0x30, 0x6E, 0x72,
0x64, 0x70, 0x61, 0x6E, 0x6E, 0x47, 0x65, 0x67, 0x77, 0x39, 0x63, 0x69, 0x46, 0x42, 0x70, 0x6E,
0x36, 0x2B, 0x38, 0x44, 0x6F, 0x4D, 0x56, 0x71, 0x2B, 0x47, 0x75, 0x51, 0x34, 0x45, 0x48, 0x76,
0x78, 0x6E, 0x56, 0x58, 0x50, 0x35, 0x4F, 0x59, 0x7A, 0x44, 0x50, 0x36, 0x47, 0x6D, 0x79, 0x75,
0x43, 0x73, 0x7A, 0x76, 0x47, 0x6D, 0x4B, 0x4E, 0x54, 0x0D, 0x0A, 0x34, 0x2B, 0x2F, 0x4B, 0x78,
0x7A, 0x38, 0x32, 0x46, 0x48, 0x6A, 0x71, 0x79, 0x6B, 0x67, 0x41, 0x32, 0x41, 0x76, 0x44, 0x2F,
0x39, 0x6D, 0x4F, 0x4C, 0x53, 0x61, 0x4F, 0x68, 0x4B, 0x6E, 0x66, 0x73, 0x38, 0x43, 0x64, 0x58,
0x78, 0x2B, 0x30, 0x72, 0x33, 0x4A, 0x31, 0x78, 0x58, 0x4D, 0x55, 0x38, 0x30, 0x37, 0x64, 0x6A,
0x57, 0x42, 0x4C, 0x38, 0x4B, 0x42, 0x55, 0x67, 0x54, 0x54, 0x66, 0x0D, 0x0A, 0x62, 0x4A, 0x79,
0x50, 0x50, 0x6C, 0x6D, 0x30, 0x57, 0x6C, 0x66, 0x79, 0x37, 0x64, 0x79, 0x57, 0x55, 0x78, 0x54,
0x38, 0x50, 0x46, 0x6D, 0x6F, 0x58, 0x45, 0x52, 0x38, 0x71, 0x75, 0x36, 0x71, 0x68, 0x66, 0x6D,
0x77, 0x39, 0x6F, 0x63, 0x4C, 0x43, 0x70, 0x34, 0x6C, 0x61, 0x42, 0x75, 0x36, 0x66, 0x46, 0x63,
0x49, 0x34, 0x50, 0x6F, 0x3D, 0x0D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20,
0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
0x0D, 0x0A
};
//File: key.pem, Size: 1732
#define key_pem_len 1732
const uint8_t key_pem[] PROGMEM = {
0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41,
0x54, 0x45, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0D, 0x0A, 0x4D, 0x49, 0x49,
0x45, 0x76, 0x67, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69,
0x47, 0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, 0x42, 0x4B, 0x67,
0x77, 0x67, 0x67, 0x53, 0x6B, 0x41, 0x67, 0x45, 0x41, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x44,
0x48, 0x65, 0x53, 0x55, 0x4B, 0x31, 0x44, 0x57, 0x67, 0x73, 0x67, 0x71, 0x33, 0x0D, 0x0A, 0x31,
0x71, 0x31, 0x64, 0x46, 0x54, 0x31, 0x35, 0x75, 0x33, 0x4E, 0x57, 0x49, 0x4B, 0x46, 0x53, 0x4C,
0x6C, 0x31, 0x75, 0x79, 0x36, 0x37, 0x54, 0x49, 0x43, 0x74, 0x39, 0x32, 0x57, 0x38, 0x58, 0x54,
0x71, 0x43, 0x69, 0x44, 0x58, 0x50, 0x6D, 0x71, 0x38, 0x55, 0x7A, 0x5A, 0x59, 0x51, 0x49, 0x50,
0x55, 0x74, 0x6A, 0x34, 0x39, 0x6B, 0x58, 0x6D, 0x4F, 0x53, 0x6F, 0x4E, 0x6D, 0x6F, 0x4B, 0x0D,
0x0A, 0x65, 0x2F, 0x61, 0x58, 0x64, 0x50, 0x76, 0x37, 0x31, 0x75, 0x45, 0x34, 0x68, 0x71, 0x4A,
0x2F, 0x5A, 0x4F, 0x77, 0x52, 0x46, 0x50, 0x48, 0x73, 0x48, 0x51, 0x77, 0x7A, 0x76, 0x48, 0x58,
0x75, 0x79, 0x55, 0x57, 0x33, 0x4E, 0x74, 0x46, 0x53, 0x50, 0x41, 0x55, 0x64, 0x36, 0x30, 0x45,
0x57, 0x70, 0x62, 0x71, 0x4B, 0x65, 0x57, 0x63, 0x67, 0x77, 0x6D, 0x7A, 0x42, 0x33, 0x43, 0x6D,
0x56, 0x0D, 0x0A, 0x57, 0x76, 0x56, 0x36, 0x6F, 0x64, 0x6C, 0x69, 0x52, 0x42, 0x72, 0x4A, 0x62,
0x6C, 0x71, 0x56, 0x63, 0x6F, 0x4C, 0x54, 0x59, 0x32, 0x51, 0x4C, 0x47, 0x31, 0x46, 0x59, 0x75,
0x4E, 0x6F, 0x78, 0x39, 0x6F, 0x71, 0x61, 0x4C, 0x55, 0x6F, 0x6F, 0x58, 0x6C, 0x63, 0x74, 0x59,
0x59, 0x56, 0x53, 0x62, 0x6E, 0x48, 0x45, 0x51, 0x6C, 0x44, 0x49, 0x37, 0x71, 0x35, 0x41, 0x62,
0x2B, 0x56, 0x42, 0x0D, 0x0A, 0x47, 0x5A, 0x72, 0x4E, 0x35, 0x46, 0x41, 0x52, 0x6F, 0x51, 0x4D,
0x33, 0x37, 0x52, 0x78, 0x39, 0x58, 0x4E, 0x5A, 0x71, 0x56, 0x2B, 0x41, 0x4D, 0x30, 0x47, 0x54,
0x72, 0x73, 0x64, 0x6B, 0x6E, 0x6F, 0x7A, 0x6C, 0x6A, 0x48, 0x58, 0x72, 0x67, 0x54, 0x4E, 0x45,
0x6F, 0x56, 0x39, 0x45, 0x73, 0x66, 0x52, 0x64, 0x58, 0x62, 0x4F, 0x30, 0x47, 0x6A, 0x51, 0x31,
0x55, 0x37, 0x41, 0x62, 0x59, 0x0D, 0x0A, 0x4D, 0x49, 0x4C, 0x69, 0x61, 0x43, 0x78, 0x2B, 0x74,
0x58, 0x56, 0x58, 0x43, 0x65, 0x4E, 0x32, 0x58, 0x6B, 0x68, 0x6E, 0x75, 0x7A, 0x66, 0x61, 0x6C,
0x71, 0x6A, 0x37, 0x57, 0x55, 0x68, 0x2F, 0x6A, 0x6B, 0x54, 0x33, 0x53, 0x2F, 0x35, 0x69, 0x76,
0x31, 0x38, 0x54, 0x4A, 0x61, 0x71, 0x6B, 0x37, 0x6F, 0x30, 0x68, 0x2B, 0x47, 0x6E, 0x64, 0x61,
0x75, 0x71, 0x57, 0x32, 0x38, 0x43, 0x41, 0x0D, 0x0A, 0x6B, 0x2B, 0x69, 0x74, 0x56, 0x6B, 0x30,
0x4E, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x45, 0x43, 0x67, 0x67, 0x45, 0x42, 0x41, 0x4B, 0x64,
0x67, 0x73, 0x41, 0x52, 0x32, 0x4C, 0x4D, 0x6D, 0x36, 0x6D, 0x2B, 0x50, 0x47, 0x37, 0x35, 0x47,
0x37, 0x30, 0x4F, 0x6E, 0x6B, 0x73, 0x4E, 0x4D, 0x45, 0x62, 0x6C, 0x6C, 0x58, 0x4C, 0x6D, 0x39,
0x5A, 0x32, 0x6B, 0x69, 0x75, 0x4A, 0x64, 0x42, 0x6B, 0x0D, 0x0A, 0x4D, 0x79, 0x4F, 0x4C, 0x68,
0x70, 0x35, 0x30, 0x53, 0x31, 0x79, 0x7A, 0x70, 0x62, 0x57, 0x4B, 0x36, 0x55, 0x39, 0x41, 0x6E,
0x35, 0x49, 0x69, 0x44, 0x6E, 0x67, 0x4F, 0x67, 0x30, 0x2F, 0x69, 0x32, 0x50, 0x67, 0x54, 0x4C,
0x4D, 0x66, 0x4B, 0x45, 0x65, 0x63, 0x77, 0x56, 0x36, 0x76, 0x6D, 0x7A, 0x56, 0x4F, 0x34, 0x69,
0x35, 0x32, 0x4A, 0x78, 0x62, 0x59, 0x71, 0x61, 0x61, 0x4B, 0x2F, 0x0D, 0x0A, 0x38, 0x50, 0x56,
0x39, 0x54, 0x6C, 0x4A, 0x2B, 0x58, 0x51, 0x5A, 0x7A, 0x39, 0x70, 0x63, 0x30, 0x59, 0x46, 0x6C,
0x77, 0x6C, 0x79, 0x61, 0x36, 0x32, 0x42, 0x35, 0x56, 0x42, 0x6F, 0x31, 0x6C, 0x41, 0x44, 0x2B,
0x6A, 0x49, 0x33, 0x6A, 0x54, 0x64, 0x6D, 0x56, 0x4F, 0x59, 0x47, 0x76, 0x46, 0x66, 0x5A, 0x30,
0x4A, 0x69, 0x56, 0x31, 0x33, 0x65, 0x4F, 0x73, 0x59, 0x38, 0x52, 0x6C, 0x51, 0x0D, 0x0A, 0x42,
0x77, 0x47, 0x52, 0x2B, 0x38, 0x74, 0x67, 0x56, 0x7A, 0x53, 0x39, 0x55, 0x45, 0x71, 0x2F, 0x36,
0x2B, 0x50, 0x44, 0x35, 0x77, 0x75, 0x6C, 0x73, 0x79, 0x6F, 0x6A, 0x4D, 0x2B, 0x70, 0x39, 0x78,
0x2F, 0x72, 0x6D, 0x71, 0x36, 0x31, 0x6A, 0x63, 0x36, 0x6A, 0x63, 0x66, 0x7A, 0x71, 0x45, 0x75,
0x70, 0x7A, 0x55, 0x64, 0x69, 0x5A, 0x4D, 0x65, 0x45, 0x69, 0x75, 0x50, 0x7A, 0x4C, 0x71, 0x0D,
0x0A, 0x77, 0x5A, 0x64, 0x32, 0x65, 0x46, 0x68, 0x50, 0x51, 0x46, 0x43, 0x76, 0x64, 0x58, 0x6F,
0x55, 0x69, 0x61, 0x78, 0x53, 0x67, 0x4A, 0x2B, 0x47, 0x31, 0x54, 0x69, 0x6B, 0x44, 0x4D, 0x58,
0x61, 0x51, 0x58, 0x67, 0x55, 0x53, 0x41, 0x4D, 0x43, 0x65, 0x49, 0x42, 0x74, 0x53, 0x58, 0x4C,
0x41, 0x64, 0x4D, 0x65, 0x68, 0x70, 0x43, 0x75, 0x6C, 0x51, 0x35, 0x6C, 0x33, 0x41, 0x73, 0x38,
0x30, 0x0D, 0x0A, 0x77, 0x6B, 0x48, 0x64, 0x36, 0x72, 0x42, 0x46, 0x78, 0x6C, 0x71, 0x69, 0x74,
0x4D, 0x47, 0x4C, 0x4A, 0x30, 0x65, 0x4D, 0x47, 0x6F, 0x54, 0x58, 0x79, 0x67, 0x51, 0x77, 0x2F,
0x7A, 0x58, 0x4C, 0x6F, 0x5A, 0x62, 0x4C, 0x7A, 0x72, 0x6A, 0x66, 0x4F, 0x4D, 0x45, 0x43, 0x67,
0x59, 0x45, 0x41, 0x38, 0x30, 0x6A, 0x4E, 0x59, 0x75, 0x2F, 0x61, 0x41, 0x6B, 0x69, 0x52, 0x77,
0x4A, 0x72, 0x71, 0x0D, 0x0A, 0x74, 0x2F, 0x72, 0x6D, 0x7A, 0x30, 0x49, 0x74, 0x39, 0x33, 0x44,
0x36, 0x59, 0x6C, 0x50, 0x44, 0x32, 0x59, 0x51, 0x4B, 0x35, 0x75, 0x47, 0x52, 0x71, 0x7A, 0x76,
0x4F, 0x33, 0x6E, 0x6F, 0x6F, 0x54, 0x6B, 0x4E, 0x48, 0x65, 0x73, 0x35, 0x59, 0x54, 0x4A, 0x2B,
0x6F, 0x2B, 0x4F, 0x38, 0x61, 0x4E, 0x38, 0x61, 0x37, 0x61, 0x36, 0x73, 0x4F, 0x6B, 0x4E, 0x55,
0x66, 0x6B, 0x64, 0x64, 0x31, 0x0D, 0x0A, 0x74, 0x2B, 0x68, 0x52, 0x63, 0x63, 0x66, 0x70, 0x30,
0x6C, 0x58, 0x61, 0x61, 0x69, 0x4C, 0x77, 0x65, 0x64, 0x59, 0x67, 0x2F, 0x36, 0x2B, 0x38, 0x77,
0x64, 0x75, 0x6F, 0x47, 0x53, 0x34, 0x4C, 0x58, 0x68, 0x46, 0x52, 0x56, 0x2F, 0x47, 0x41, 0x32,
0x4B, 0x59, 0x64, 0x6C, 0x4E, 0x65, 0x74, 0x39, 0x4D, 0x6A, 0x76, 0x54, 0x6E, 0x35, 0x6C, 0x68,
0x52, 0x4B, 0x78, 0x6B, 0x44, 0x77, 0x45, 0x0D, 0x0A, 0x56, 0x36, 0x67, 0x34, 0x45, 0x2B, 0x74,
0x37, 0x59, 0x34, 0x73, 0x4F, 0x79, 0x32, 0x32, 0x74, 0x6D, 0x70, 0x54, 0x45, 0x37, 0x49, 0x30,
0x56, 0x66, 0x47, 0x73, 0x43, 0x67, 0x59, 0x45, 0x41, 0x30, 0x65, 0x59, 0x6A, 0x75, 0x74, 0x74,
0x74, 0x6A, 0x37, 0x6F, 0x70, 0x39, 0x35, 0x59, 0x76, 0x37, 0x2F, 0x57, 0x6F, 0x7A, 0x64, 0x77,
0x53, 0x48, 0x72, 0x6E, 0x4C, 0x79, 0x56, 0x32, 0x55, 0x0D, 0x0A, 0x79, 0x36, 0x52, 0x6F, 0x33,
0x79, 0x33, 0x66, 0x56, 0x71, 0x55, 0x49, 0x6A, 0x61, 0x66, 0x74, 0x4F, 0x65, 0x78, 0x41, 0x6E,
0x6E, 0x49, 0x4E, 0x53, 0x5A, 0x62, 0x56, 0x6D, 0x69, 0x6B, 0x38, 0x63, 0x51, 0x64, 0x44, 0x70,
0x49, 0x6B, 0x47, 0x46, 0x63, 0x51, 0x4C, 0x78, 0x6F, 0x69, 0x66, 0x38, 0x4A, 0x67, 0x68, 0x6D,
0x77, 0x79, 0x4A, 0x43, 0x6E, 0x53, 0x4C, 0x34, 0x58, 0x33, 0x73, 0x0D, 0x0A, 0x55, 0x6E, 0x50,
0x2B, 0x59, 0x58, 0x39, 0x57, 0x76, 0x2B, 0x67, 0x34, 0x63, 0x4B, 0x53, 0x58, 0x51, 0x48, 0x57,
0x30, 0x65, 0x4F, 0x32, 0x6E, 0x33, 0x63, 0x49, 0x71, 0x63, 0x50, 0x33, 0x4C, 0x33, 0x70, 0x67,
0x6F, 0x42, 0x31, 0x42, 0x68, 0x43, 0x77, 0x41, 0x71, 0x56, 0x6F, 0x65, 0x56, 0x42, 0x39, 0x49,
0x58, 0x71, 0x6A, 0x66, 0x33, 0x6F, 0x55, 0x51, 0x6F, 0x48, 0x63, 0x6E, 0x64, 0x0D, 0x0A, 0x68,
0x63, 0x55, 0x70, 0x35, 0x31, 0x4C, 0x44, 0x4F, 0x6D, 0x63, 0x43, 0x67, 0x59, 0x42, 0x33, 0x6C,
0x49, 0x42, 0x48, 0x73, 0x69, 0x64, 0x52, 0x57, 0x67, 0x51, 0x79, 0x54, 0x4C, 0x4D, 0x30, 0x62,
0x57, 0x49, 0x48, 0x32, 0x37, 0x71, 0x6D, 0x56, 0x6D, 0x54, 0x72, 0x38, 0x63, 0x70, 0x68, 0x58,
0x78, 0x4C, 0x51, 0x75, 0x32, 0x30, 0x54, 0x59, 0x70, 0x6C, 0x6A, 0x4A, 0x31, 0x34, 0x71, 0x0D,
0x0A, 0x59, 0x63, 0x31, 0x2F, 0x6F, 0x6D, 0x38, 0x71, 0x63, 0x6F, 0x76, 0x6D, 0x6C, 0x2F, 0x67,
0x6D, 0x46, 0x45, 0x76, 0x4A, 0x4E, 0x31, 0x49, 0x34, 0x68, 0x46, 0x6B, 0x35, 0x49, 0x56, 0x4F,
0x65, 0x61, 0x74, 0x57, 0x6C, 0x66, 0x4B, 0x4D, 0x45, 0x6E, 0x4F, 0x68, 0x33, 0x70, 0x4F, 0x62,
0x59, 0x72, 0x42, 0x53, 0x61, 0x4F, 0x50, 0x49, 0x70, 0x77, 0x32, 0x4D, 0x54, 0x78, 0x56, 0x73,
0x58, 0x0D, 0x0A, 0x43, 0x4B, 0x49, 0x58, 0x2F, 0x50, 0x2F, 0x63, 0x2F, 0x59, 0x47, 0x71, 0x79,
0x48, 0x79, 0x62, 0x78, 0x69, 0x78, 0x43, 0x51, 0x38, 0x52, 0x34, 0x72, 0x57, 0x43, 0x54, 0x79,
0x62, 0x78, 0x45, 0x72, 0x63, 0x32, 0x71, 0x6C, 0x4F, 0x4F, 0x59, 0x59, 0x53, 0x43, 0x4C, 0x67,
0x30, 0x53, 0x43, 0x70, 0x37, 0x39, 0x48, 0x6D, 0x6D, 0x31, 0x47, 0x4D, 0x77, 0x4B, 0x42, 0x67,
0x51, 0x44, 0x41, 0x0D, 0x0A, 0x70, 0x55, 0x38, 0x70, 0x30, 0x76, 0x63, 0x74, 0x73, 0x52, 0x6D,
0x50, 0x69, 0x61, 0x4B, 0x5A, 0x78, 0x49, 0x69, 0x58, 0x32, 0x47, 0x49, 0x78, 0x48, 0x53, 0x6D,
0x79, 0x75, 0x56, 0x63, 0x31, 0x79, 0x4D, 0x49, 0x51, 0x42, 0x46, 0x51, 0x31, 0x65, 0x2B, 0x62,
0x72, 0x7A, 0x4C, 0x4A, 0x6F, 0x4E, 0x54, 0x50, 0x68, 0x75, 0x4B, 0x41, 0x46, 0x61, 0x4A, 0x44,
0x48, 0x6D, 0x77, 0x31, 0x45, 0x0D, 0x0A, 0x56, 0x2F, 0x78, 0x33, 0x61, 0x4F, 0x50, 0x53, 0x32,
0x6B, 0x70, 0x4D, 0x66, 0x31, 0x7A, 0x38, 0x50, 0x30, 0x53, 0x6F, 0x76, 0x38, 0x71, 0x50, 0x64,
0x41, 0x52, 0x6D, 0x67, 0x32, 0x4B, 0x42, 0x45, 0x73, 0x44, 0x6F, 0x7A, 0x79, 0x7A, 0x5A, 0x6D,
0x64, 0x4D, 0x6A, 0x58, 0x34, 0x30, 0x4B, 0x74, 0x6E, 0x31, 0x62, 0x65, 0x42, 0x52, 0x58, 0x37,
0x6A, 0x74, 0x78, 0x31, 0x52, 0x35, 0x6D, 0x0D, 0x0A, 0x51, 0x4A, 0x53, 0x4D, 0x6B, 0x66, 0x4E,
0x66, 0x57, 0x31, 0x6D, 0x41, 0x62, 0x5A, 0x51, 0x55, 0x78, 0x33, 0x69, 0x38, 0x32, 0x2F, 0x31,
0x46, 0x58, 0x2F, 0x37, 0x4A, 0x79, 0x46, 0x71, 0x75, 0x79, 0x68, 0x54, 0x35, 0x6F, 0x50, 0x5A,
0x61, 0x42, 0x51, 0x4B, 0x42, 0x67, 0x47, 0x77, 0x44, 0x79, 0x64, 0x35, 0x34, 0x36, 0x58, 0x62,
0x77, 0x4D, 0x65, 0x33, 0x77, 0x43, 0x31, 0x69, 0x5A, 0x0D, 0x0A, 0x42, 0x4A, 0x76, 0x70, 0x6C,
0x68, 0x4A, 0x53, 0x6E, 0x43, 0x34, 0x32, 0x50, 0x61, 0x70, 0x4F, 0x4F, 0x58, 0x46, 0x55, 0x6B,
0x63, 0x67, 0x32, 0x63, 0x63, 0x65, 0x37, 0x69, 0x59, 0x50, 0x6B, 0x37, 0x5A, 0x50, 0x4F, 0x67,
0x57, 0x72, 0x57, 0x54, 0x70, 0x39, 0x53, 0x52, 0x41, 0x68, 0x49, 0x45, 0x54, 0x66, 0x75, 0x41,
0x6E, 0x67, 0x47, 0x38, 0x57, 0x71, 0x52, 0x36, 0x37, 0x71, 0x63, 0x0D, 0x0A, 0x7A, 0x4C, 0x44,
0x52, 0x42, 0x51, 0x67, 0x42, 0x73, 0x66, 0x30, 0x71, 0x41, 0x2B, 0x50, 0x6C, 0x66, 0x66, 0x39,
0x45, 0x62, 0x63, 0x31, 0x71, 0x7A, 0x6A, 0x31, 0x79, 0x51, 0x32, 0x64, 0x53, 0x31, 0x61, 0x76,
0x72, 0x55, 0x75, 0x72, 0x78, 0x4F, 0x4F, 0x5A, 0x55, 0x63, 0x53, 0x7A, 0x71, 0x57, 0x56, 0x4C,
0x5A, 0x2F, 0x7A, 0x33, 0x4F, 0x4E, 0x32, 0x4E, 0x4E, 0x45, 0x58, 0x76, 0x53, 0x0D, 0x0A, 0x67,
0x51, 0x32, 0x70, 0x62, 0x4A, 0x7A, 0x61, 0x75, 0x78, 0x4F, 0x71, 0x59, 0x57, 0x56, 0x74, 0x36,
0x41, 0x7A, 0x6F, 0x74, 0x7A, 0x6B, 0x4E, 0x0D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E,
0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D,
0x2D, 0x2D, 0x0D, 0x0A
};
// The HTTPS Server comes in a separate namespace. For easier use, include it here.
using namespace httpsserver;
// Create an SSL certificate object from the files included above
SSLCert cert = SSLCert(
(unsigned char *)cert_pem, cert_pem_len,
(unsigned char *)key_pem, key_pem_len
);
// Create an SSL-enabled server that uses the certificate
// The contstructor takes some more parameters, but we go for default values here.
HTTPSServer secureServer = HTTPSServer(&cert);
void handleRoot(HTTPRequest * req, HTTPResponse * res);
void handleFormUpload(HTTPRequest * req, HTTPResponse * res);
void handle404(HTTPRequest * req, HTTPResponse * res);
void setup() {
// For logging
Serial.begin(115200);
// Connect to WiFi
Serial.println("Setting up WiFi");
WiFi.begin(WIFI_SSID, WIFI_PSK);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("Connected. IP=");
Serial.println(WiFi.localIP());
ResourceNode * nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
ResourceNode * nodeForm = new ResourceNode("/upload", "GET", &handleRoot);
// 404 node has no URL as it is used for all requests that don't match anything else
ResourceNode * node404 = new ResourceNode("", "GET", &handle404);
// Add all nodes to the server so they become accessible:
secureServer.registerNode(nodeForm);
secureServer.registerNode(nodeFormUpload);
secureServer.setDefaultNode(node404);
Serial.println("Starting server...");
secureServer.start();
if (secureServer.isRunning()) {
Serial.println("Server ready.");
}
}
void loop() {
// This call will let the server do its work
secureServer.loop();
delay(1);
}
static const char serverIndex[] PROGMEM =
R"(<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'/>
</head>
<body>
<form method='POST' action='' enctype='multipart/form-data'>
Firmware:<br>
<input type='file' accept='.bin,.bin.gz' name='firmware'>
<input type='submit' value='Update Firmware'>
</form>
<form method='POST' action='' enctype='multipart/form-data'>
FileSystem:<br>
<input type='file' accept='.bin,.bin.gz,.image' name='filesystem'>
<input type='submit' value='Update FileSystem'>
</form>
</body>
</html>)";
static const char successResponse[] PROGMEM =
"<p>Update Success! Reset device and restart webpage.</p>";
void handleRoot(HTTPRequest * req, HTTPResponse * res) {
res->setHeader("Content-Type", "text/html");
// Just the regular HTML document structure, nothing special to forms here....
res->println(serverIndex);
}
void handleFormUpload(HTTPRequest * req, HTTPResponse * res) {
HTTPBodyParser *parser;
std::string contentType = req->getHeader("Content-Type");
size_t semicolonPos = contentType.find(";");
if (semicolonPos != std::string::npos) {
contentType = contentType.substr(0, semicolonPos);
}
// Now, we can decide based on the content type:
if (contentType == "multipart/form-data") {
parser = new HTTPMultipartBodyParser(req);
} else {
Serial.printf("Unknown POST Content-Type: %s\n", contentType.c_str());
return;
}
while(parser->nextField()) {
std::string name = parser->getFieldName();
std::string filename = parser->getFieldFilename();
std::string mimeType = parser->getFieldMimeType();
Serial.printf("handleFormUpload: field name='%s', filename='%s', mimetype='%s'\n", name.c_str(), filename.c_str(), mimeType.c_str());
if (name != "firmware" && name != "filesystem" ) {
Serial.println("Skipping unexpected field");
break;
}
if (name == "filesystem") {
Serial.println(F("Filesystem update found!"));
if (!Update.begin(SPIFFS.totalBytes(), U_SPIFFS)) {//start with max available size
Update.printError(Serial);
}
}
else {
Serial.println(F("Firmware update found!"));
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace, U_FLASH)) {//start with max available size
Update.printError(Serial);
}
}
Serial.println(F("Starting update!"));
size_t fileLength = 0;
while (!parser->endOfField()) {
byte buf[512];
size_t readLength = parser->read(buf, 512);
if (Update.write(buf, readLength) != readLength) {
Update.printError(Serial);
}
fileLength += readLength;
Serial.printf("Upload and updated %u byte\n", fileLength);
}
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\n", fileLength);
// res->println("<p>Update Success: \nRebooting...\n</p>");
res->println(successResponse);
}
else {
Update.printError(Serial);
res->println(Update.getError());
}
}
delete parser;
}
void handle404(HTTPRequest * req, HTTPResponse * res) {
req->discardRequestBody();
res->setStatusCode(404);
res->setStatusText("Not Found");
res->setHeader("Content-Type", "text/html");
res->println("<!DOCTYPE html>");
res->println("<html>");
res->println("<head><title>Not Found</title></head>");
res->println("<body><h1>404 Not Found</h1><p>The requested resource was not found on this server.</p></body>");
res->println("</html>");
}
In questo sketch, creiamo il certificato con il contenuto di cer e key.
// Create an SSL certificate object from the files above
SSLCert cert = SSLCert(
(unsigned char *)cert_pem, cert_pem_len,
(unsigned char *)key_pem, key_pem_len
);
// Create an SSL-enabled server that uses the certificate
// The contstructor takes some more parameters, but we go for default values here.
HTTPSServer secureServer = HTTPSServer(&cert);
E pubblicheremo l’endpoint di caricamento in GET per la pagina e in POST per caricare il firmware.
ResourceNode * nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
ResourceNode * nodeForm = new ResourceNode("/upload", "GET", &handleRoot);
// 404 node has no URL as it is used for all requests that don't match anything else
ResourceNode * node404 = new ResourceNode("", "GET", &handle404);
// Add all nodes to the server so they become accessible:
secureServer.registerNode(nodeForm);
secureServer.registerNode(nodeFormUpload);
secureServer.setDefaultNode(node404);
Riutilizzo la pagina dell’HTTPUpdateServer.
static const char serverIndex[] PROGMEM =
R"(<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'/>
</head>
<body>
<form method='POST' action='' enctype='multipart/form-data'>
Firmware:<br>
<input type='file' accept='.bin,.bin.gz' name='firmware'>
<input type='submit' value='Update Firmware'>
</form>
<form method='POST' action='' enctype='multipart/form-data'>
FileSystem:<br>
<input type='file' accept='.bin,.bin.gz,.image' name='filesystem'>
<input type='submit' value='Update FileSystem'>
</form>
</body>
</html>)";
Successivamente, quando riceviamo i dati del modulo POST, verificheremo se si tratta di firmware o filesystem e chiameremo il begin
della classe Update
con il parametro corretto U_FLASH
o U_FS
.
if (name == "filesystem") {
Serial.println(F("Filesystem update found!"));
if (!Update.begin(SPIFFS.totalBytes(), U_SPIFFS)) {//start with max available size
Update.printError(Serial);
}
}
else {
Serial.println(F("Firmware update found!"));
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if (!Update.begin(maxSketchSpace, U_FLASH)) {//start with max available size
Update.printError(Serial);
}
}
Quando lo stream inizia, userò Update.write
while (!parser->endOfField()) {
byte buf[512];
size_t readLength = parser->read(buf, 512);
if (Update.write(buf, readLength) != readLength) {
Update.printError(Serial);
}
fileLength += readLength;
Serial.printf("Upload and updated %u byte\n", fileLength);
}
E infine, l’end
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\n", fileLength);
// res->println("<p>Update Success: \nRebooting...\n</p>");
res->println(successResponse);
}
else {
Update.printError(Serial);
res->println(Update.getError());
}
Con un certificato autofirmato senza una vera autorità di certificazione, quando provi ad aprire il browser ti invia un messaggio per informarti del potenziale rischio, ma la connessione sarà comunque criptata.
Grazie
- ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
- ESP32: fileSystem integrato SPIFFS
- ESP32: gestire più seriali e logging per il debug
- ESP32 risparmio energetico pratico
- ESP32 risparmio energetico pratico: gestire WiFi e CPU
- ESP32 risparmio energetico pratico: modem e light sleep
- ESP32 risparmio energetico pratico: deep sleep e ibernazione
- ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
- ESP32 risparmio energetico pratico: sveglia esterna e da ULP
- ESP32 risparmio energetico pratico: sveglia da UART e GPIO
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (Fat/exFAT)
- ESP32-wroom-32
- ESP32-CAM
- ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
- ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
- Come usare la scheda SD con l’esp32
- esp32 e esp8266: file system FAT su memoria SPI flash esterna
- Gestione aggiornamenti firmware e OTA
- Gestione del firmware
- Aggiornamento OTA con Arduino IDE
- Aggiornamento OTA con browser web
- Aggiornamenti automatici OTA da un server HTTP
- Aggiornamento del firmware non standard
- Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
- Collegare l’EByte E70 (CC1310) ai dispositivi ESP32 c3/s3 ed un semplice sketch di esempio
- ESP32-C3: piedinatura, specifiche e configurazione dell’IDE Arduino
- Integrazione del modulo W5500 su ESP32 con Core 3: supporto nativo ai protocolli Ethernet con SSL e altre funzionalità
- Integrazione del modulo LAN8720 su ESP32 con Core 3: supporto nativo del protocollo Ethernet con SSL e altre funzionalità.