123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /**
- Bibliothèque pour avoir une mise à jour Over The Air d'un code source.
- Utilisation :
- Dans le setup, rajouter OTA_setup();
- Dans la loop, rajouter OTA_doUpdate();
- Fonctionnement :
- Toutes les OTA_TimerInSecond secondes, le programme va vérifier qu'il y a une mise à jour sur le serveur.
- Si une mise à jour existe, elle est téléchargée et installé et l'ESP reboot.
- S'il n'y a pas de mise à jour, le serveur le dit et on ne fait rien.
-
- Avant toutes upload de ce script dans un Arduino, il faut executer un script Python de récupération de certificats qui
- se trouve sur le repot https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/BearSSL_CertStore/certs-from-mozilla.py
- */
-
- #include <ESP8266WiFi.h>
- #include <ESP8266WiFiMulti.h>
-
- #include <ESP8266HTTPClient.h>
- #include <ESP8266httpUpdate.h>
- char outputBuffer[100]; // Pour les messages à afficher
- char macAdresse[12];
-
- // Fait un serveur de mise à jour local dans l'ESP
- #include <ESP8266HTTPUpdateServer.h>
- #include <ESP8266WebServer.h>
- ESP8266WebServer OTA_HttpServer(80);
- ESP8266HTTPUpdateServer OTA_httpUpdater;
- const char* OTA_update_username = "ESPadmin";
- const char* OTA_update_password = "admin";
- const char* OTA_update_path = "/firmware";
- boolean g_BOO_UpdateFirmware = true;
-
-
- const String firmwareUrlMiseAJour = "https://update.alex-design.fr/MQTT-leds-color/update.php";
- const String fileSystemUrlMiseAJour = "https://update.alex-design.fr/MQTT-leds-color/updateFS.php";
- //const String firmwareUrlMiseAJour = "http://192.168.0.32:9090/MQTT-leds-color/update.php"; <- Ne peut pas fonctionner car il est en http, et on veut du https
- // Define global variable to know if upate is available
- long OTA_UpdateTimer;
- const int OTA_TimerInSecond = 60 * 10; // every 10 minute
-
-
- // Utilisation d'un certificat ------------------------------------------
- // Pour mettre à jour l'heure (obligatoire avec un certificat https)
- #include <time.h>
- // A single, global CertStore which can be used by all
- // connections. Needs to stay live the entire time any of
- // the WiFiClientBearSSLs are present.
- #include <CertStoreBearSSL.h>
- BearSSL::CertStore certStore;
- #include <FS.h>
- #include <LittleFS.h>
- char versionLitteFS[10] = "0.0.0";
-
-
- // Define a wifi client
- ESP8266WiFiMulti WiFiMulti;
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Callback lorsque la maj OTA démarre
- */
- void _update_started() {
- DEBUG("CALLBACK: HTTPS update process started");
- }
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Callback lorsque la maj OTA est terminée
- */
- void _update_finished() {
- DEBUG("CALLBACK: HTTPS update process finished. Reboot");
- }
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Callback lorsque la maj OTA est en cours
- */
- void _update_progress(int cur, int total) {
- sprintf(outputBuffer, "CALLBACK: HTTPS update process at %d of %d bytes...", cur, total);
- DEBUG( outputBuffer );
- }
-
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Callback lorsque la maj OTA a plantée
- */
- void _update_error(int err) {
- sprintf(outputBuffer, "CALLBACK: HTTPS update fatal error code %d\n", err);
- DEBUG( outputBuffer );
-
- if (err == -103) {
- DEBUG(" Please allow me, I am ");
- DEBUG(WiFi.macAddress());
- DEBUG(WiFi.localIP());
- }
-
- if ( err == 0 ) {
- DEBUG("La mise à jour du firmware via OTA n'a pas marché, on stop !!!!!!!!!!!!");
- g_BOO_UpdateFirmware = false;
- }
- }
-
-
-
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Set time via NTP, as required for x.509 validation
- ----------------------------------------------------------------------------------------------------------------
- */
- void OTA_setClock() {
- configTime(0, 0, "pool.ntp.org", "time.nist.gov"); // UTC
- DEBUG("OTA Waiting for NTP time sync: ");
- time_t now = time(nullptr);
- while (now < 8 * 3600 * 2) {
- yield();
- delay(500);
- Serial.print(F("."));
- now = time(nullptr);
- }
- struct tm timeinfo;
- gmtime_r(&now, &timeinfo);
-
- DEBUG("Current time: ");
- DEBUG(asctime(&timeinfo));
- }
-
-
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Initialisation d'une connexion wifi à l'aide des settings de wifimanager en eeprom.
- ----------------------------------------------------------------------------------------------------------------
- */
- void OTA_setup() {
-
- /* Mise en place d'un serveur pour uploader directement un binaire */
- OTA_httpUpdater.setup(&OTA_HttpServer, OTA_update_path, OTA_update_username, OTA_update_password);
- OTA_HttpServer.begin();
- sprintf(outputBuffer, "OTA HTTPUpdateServer ready! Open http://%d.%d.%d.%d%s in your browser and login with username '%s' and password '%s'\n",
- WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], OTA_update_path, OTA_update_username, OTA_update_password);
- DEBUG(outputBuffer);
- MQTT_publishDebug(String(outputBuffer));
-
-
-
-
- // Test la version du file system littleFS en place
- if ( !LittleFS.begin()) {
- DEBUG("Il n'y a pas de file system little FS installé, lecture impossible !");
-
- } else {
- // Get version of the certificat in LittleFS (frome file version.txt
- File file = LittleFS.open("/version.txt", "r");
- if ( file ) {
- while (file.available()) {
- strcpy(versionLitteFS, file.readString().c_str() );
- }
- file.close();
- }
-
- // Récupération des CA stockés dans LittleFS pour les certificats SSL
- int numCerts = certStore.initCertStore(LittleFS, PSTR("/certs.idx"), PSTR("/certs.ar"));
- DEBUG("Number of CA certs read: ");
- DEBUG(numCerts);
- if (numCerts == 0) {
- DEBUG(F("No certs found. Did you run certs-from-mozill.py and upload the LittleFS directory before running?"));
- }
- }
- DEBUG("Numéro de version de littleFS : " + String(versionLitteFS) );
-
-
- // Création de la connection Wifi à partir du SSID et PWD sauvé par wifimanager
- /*
- WiFi.mode(WIFI_STA);
- WiFiMulti.addAP(wifiManager.getWiFiSSID(true).c_str(), wifiManager.getWiFiPass(true).c_str());
- */
-
- // We will request a firmware update in OTA_TimerInSecond secondes
- OTA_UpdateTimer = (OTA_TimerInSecond * 1000);
- }
-
-
-
-
-
- /**
- ----------------------------------------------------------------------------------------------------------------
- Va voir sur l'URL si une mise à jour du firmware est disponible. Si c'est le cas,
- la télécharge et met à jour le firmeware.
- ----------------------------------------------------------------------------------------------------------------
- */
- boolean OTA_doUpdate() {
- // Si on a pas besoin de faire de mise à jour (ou ça c'est planté la dernière fois)
- if ( !g_BOO_UpdateFirmware ) {
- return false;
- }
-
- // Fait tourner le serveur http sur l'ESP
- // Lorsqu'on se connect à ce serveur, il est possible d'uploader un firmware ou un filesystem
- OTA_HttpServer.handleClient();
-
- // Check is this is the time to check a new update
- delay( 1 ); // Wait 1 milliseconde
- if (OTA_UpdateTimer > 0 ) {
- OTA_UpdateTimer--;
- return false;
- }
-
- if (WiFiMulti.run() == WL_CONNECTED) {
- // WiFiClient client; // Client simple (incompatioble en https )
-
- // Mise à jour de l'heure via un serveur NTP
- OTA_setClock();
-
- // Récupération du certificat SSL pour la connexion https
- BearSSL::WiFiClientSecure client; // Client securise
- bool mfln = client.probeMaxFragmentLength(fileSystemUrlMiseAJour, 443, 1024); // server must be the same as in ESPhttpUpdate.update()
- if (mfln) {
- client.setBufferSizes(1024, 1024);
- }
- client.setCertStore(&certStore);
-
- // Add optional callback notifiers
- ESPhttpUpdate.onStart(_update_started);
- ESPhttpUpdate.onEnd(_update_finished);
- ESPhttpUpdate.onProgress(_update_progress);
- ESPhttpUpdate.onError(_update_error);
- ESPhttpUpdate.setLedPin(LED_BUILTIN, LOW);
-
-
- // Get the mac adresse in a char
- snprintf(macAdresse, 12, "%06X", (uint32_t)ESP.getChipId() );
-
-
- // Try to update the filesystem
- DEBUG(fileSystemUrlMiseAJour + "?chipID=" + String(macAdresse) );
- t_httpUpdate_return ret = ESPhttpUpdate.updateFS(client, fileSystemUrlMiseAJour + "?chipID=" + String(macAdresse), versionLitteFS);
- if (ret == HTTP_UPDATE_OK) {
- DEBUG("Update FileSystem Successfully");
- }
-
-
- // Try to update the firmware
- DEBUG(firmwareUrlMiseAJour + "?chipID=" + String(macAdresse) );
- DEBUG("Version firmware :" + firmwareActualVersion );
-
- ret = ESPhttpUpdate.update(client, firmwareUrlMiseAJour + "?chipID=" + String(macAdresse), firmwareActualVersion);
- switch (ret) {
- case HTTP_UPDATE_FAILED:
-
- sprintf(outputBuffer, "HTTP_UPDATE_FAILED Error (%d): %s\n", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
- DEBUG( outputBuffer );
-
- OTA_UpdateTimer = (OTA_TimerInSecond * 1000);
- break;
-
-
- case HTTP_UPDATE_NO_UPDATES:
- DEBUG("No new update available");
-
- OTA_UpdateTimer = (OTA_TimerInSecond * 1000);
- break;
-
- default:
- break;
- }
-
- return true;
- }
- return false;
- }
|