diff --git a/firmware/certificate.pem b/firmware/certificate.pem new file mode 100644 index 0000000..6f22b62 --- /dev/null +++ b/firmware/certificate.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIUInVjiDpmIyiLEozlQrMAJs6OuQAwDQYJKoZIhvcNAQEL +BQAwgZYxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMRIwEAYDVQQHDAlO +dXJlbWJlcmcxEjAQBgNVBAoMCUJhdWVyVGVjaDEmMCQGA1UEAwwdc3dpbXRyYWNr +ZXItdXBkYXRlLmJhdWVyLnRlY2gxJTAjBgkqhkiG9w0BCQEWFnN3aW10cmFja2Vy +QGJhdWVyLnRlY2gwHhcNMjAwODA4MTEyNjI2WhcNMjMxMTIxMTEyNjI2WjCBljEL +MAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExEjAQBgNVBAcMCU51cmVtYmVy +ZzESMBAGA1UECgwJQmF1ZXJUZWNoMSYwJAYDVQQDDB1zd2ltdHJhY2tlci11cGRh +dGUuYmF1ZXIudGVjaDElMCMGCSqGSIb3DQEJARYWc3dpbXRyYWNrZXJAYmF1ZXIu +dGVjaDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMxtQgj/EUQ7nvvU +omPeazJmeLlzm1aNPdJ/eIw/r5dfITw3GqwvcjB/X1DmJav8QEBCL+IjBPesNKVJ +Kr2J6LUjEKonOqC1wCPQJrNn+4mUfGd6MTisPTX1Z7qqA6zEge2yucxyiowhgz8d +SWQkte4iW9GJOWQwiSwj04T013aQgBWtzStum7RZCQgXtf241rMZf3SqQODqs9AW +WzO22ZIhsTpZX5Mhn88z3TDA9SdcCZdIjBB+XnUODQGS4Sv2JES1vNwNc5C2NJHt +pl9PsCXOWhLGJeVzSQHCf0LzxcsCJDKohU1wKq0ExAZOBFkkIF78crHBo8n182dO +qBpM3aUCAwEAAaNTMFEwHQYDVR0OBBYEFIHSmA+lI7g5lFbbxigzW0s5zp07MB8G +A1UdIwQYMBaAFIHSmA+lI7g5lFbbxigzW0s5zp07MA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBADKAF4kGgDdBnbjMiZhrKyf+peaVvVJe6wIEAFx/ +oO1PcFImtUUJmCOgU9AFR/SoxH8Qii/MDnPjVX4QOsAoDVU+YYVySJOuzhcNsKB1 +ZOs417BdRmg/L8UG7o3M7ZeQsYpHMyaoGDHDXAjouTf11f0bjN/xCfldj4znNtSE +zm5kIvWJA08GINILybpvSeWqJTQQPQPIXxfkHFLBJMk9JiDwdM91SfeUdLd49qM5 +h5YzB5vNB7odhXItqCuB3doXVTaXu+OMUk0Fvl1W/Um8NZcpZDZtZoI9QkBDx5Nz +HZEYVPXAcx4SPYeKEWnc+b2OJOIgzKWEWD+MTol2PaAY0cA= +-----END CERTIFICATE----- diff --git a/firmware/lib/esphttp/WebDAV.cpp b/firmware/lib/esphttp/WebDAV.cpp index b801516..5bf583e 100644 --- a/firmware/lib/esphttp/WebDAV.cpp +++ b/firmware/lib/esphttp/WebDAV.cpp @@ -114,6 +114,9 @@ std::function webdavHandler(const char *uriPrefix, String uri = String(req->uri).substring(strlen(uriPrefix)); constexpr size_t WEBDAV_BUFF_LEN = 1024 * 256; static char *webdavBuffer = (char *)heap_caps_malloc(WEBDAV_BUFF_LEN, MALLOC_CAP_SPIRAM); + + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + switch (req->method) { case HTTP_GET: @@ -139,7 +142,7 @@ std::function webdavHandler(const char *uriPrefix, httpd_resp_send(req, webdavBuffer, bytesWritten); break; } - case HTTP_DELETE: + case HTTP_DELETE: { httpd_resp_set_hdr(req, "Content-Type", "text/plain"); @@ -149,7 +152,16 @@ std::function webdavHandler(const char *uriPrefix, httpd_resp_send_404(req); break; } + case HTTP_OPTIONS: + { + Serial.println("Options request"); + httpd_resp_set_status(req, "204 No Content"); + httpd_resp_set_hdr(req, "Access-Control-Allow-Methods", "GET, PROPFIND, DELETE, OPTIONS"); + httpd_resp_send(req, "", 0); + break; + } default: + Serial.printf("Sending 404 %d uri %s\n", req->method, req->uri); httpd_resp_send_404(req); } }; diff --git a/firmware/partitions_custom.csv b/firmware/partitions_custom.csv new file mode 100644 index 0000000..4dd161c --- /dev/null +++ b/firmware/partitions_custom.csv @@ -0,0 +1,8 @@ +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, , 0x2000, +phy_init, data, phy, , 0x1000, +ota_0, 0, ota_0, , 0x110000, +ota_1, 0, ota_1, , 0x110000, +spiffs, data, spiffs, , 0x110000, diff --git a/firmware/platformio.ini b/firmware/platformio.ini index 3eb5573..a92f29d 100644 --- a/firmware/platformio.ini +++ b/firmware/platformio.ini @@ -29,6 +29,9 @@ lib_deps = HX711@0.7.4 https://github.com/gilmaimon/ArduinoWebsockets.git src_filter = +<*> - +board_build.partitions = partitions_custom.csv +board_build.embed_txtfiles = + certificate.pem [env:native] platform = native diff --git a/firmware/src/firmware_main.cpp b/firmware/src/firmware_main.cpp index 32736a9..9ed1a78 100644 --- a/firmware/src/firmware_main.cpp +++ b/firmware/src/firmware_main.cpp @@ -6,7 +6,6 @@ #include #include - // Own libs #include "MockScale.h" #include "Scale.h" @@ -18,12 +17,38 @@ #include "WebDAV.h" #include "WebsocketServer.h" +#include "esp_https_ota.h" + using Session_T = SimpleMeasurementSession; SessionManager sessionManager(CONFIG_SCALE_DOUT_PIN, CONFIG_SCALE_SCK_PIN, CONFIG_TARE_AVG_COUNT); EspHttp espHttpServer; WebsocketServer webSocketServer(sessionManager, 81); +extern const uint8_t certificate_pem[] asm("_binary_certificate_pem_start"); + +bool firmwareUpdate() +{ + esp_http_client_config_t config; + Serial.println((char *)certificate_pem); + memset(&config, 0, sizeof(esp_http_client_config_t)); + config.url = "https://swimtracker-update.bauer.tech/firmware.bin"; + config.cert_pem = (char *)certificate_pem; + Serial.println("Starting firmware upgrade"); + esp_err_t ret = esp_https_ota(&config); + if (ret == ESP_OK) + { + Serial.println("Firmware upgrade successful - restarting"); + esp_restart(); + } + else + { + Serial.println("Firmware upgrade failed"); + return false; + } + return true; +} + template void httpSetup(SessionManager *sessionManager) { @@ -47,6 +72,11 @@ void httpSetup(SessionManager *sessionManager) Serial.println("Tare"); sessionManager->tare(); }; + auto cbFirmwareUpdate = [](httpd_req_t * req) { + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + httpd_resp_send(req, "OK", -1); + firmwareUpdate(); + }; auto cbStatus = [sessionManager](httpd_req_t *req) { String result; result.reserve(512); @@ -132,13 +162,39 @@ void httpSetup(SessionManager *sessionManager) espHttpServer.on("/api/status", HTTP_GET, cbStatus); espHttpServer.on("/api/tare", HTTP_GET, cbTare); espHttpServer.on("/api/restart", HTTP_GET, cbRestart); + espHttpServer.on("/api/firmwareupdate", HTTP_GET, cbFirmwareUpdate); + auto webdav = webdavHandler("/webdav/", "/dat"); espHttpServer.on("/webdav/*?", HTTP_GET, webdav); espHttpServer.on("/webdav/*?", HTTP_PROPFIND, webdav); espHttpServer.on("/webdav/*?", HTTP_DELETE, webdav); + espHttpServer.on("/webdav/*?", HTTP_OPTIONS, webdav); + Serial.println("HTTP setup done"); } +void checkWifi() +{ + while (WiFi.status() != WL_CONNECTED) + { + Serial.println("WiFi disconnected. Try to reconnect"); + WiFi.disconnect(); + WiFi.mode(WIFI_OFF); + WiFi.mode(WIFI_STA); + WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); + delay(200); + } +} + +String getIdSuffix() +{ + uint8_t baseMac[6]; + esp_read_mac(baseMac, ESP_MAC_WIFI_STA); + char baseMacChr[18] = {0}; + sprintf(baseMacChr, "-%02X%02X%02X", baseMac[3], baseMac[4], baseMac[5]); + return String(baseMacChr); +} + void setup() { // Serial @@ -158,7 +214,8 @@ void setup() // WiFi WiFi.mode(WIFI_STA); WiFi.begin(CONFIG_WIFI_SSID, CONFIG_WIFI_PASSWORD); - WiFi.setHostname(CONFIG_HOSTNAME); + String fullHostname = String(CONFIG_HOSTNAME) + getIdSuffix(); + WiFi.setHostname(fullHostname.c_str()); Serial.println(F("Waiting for WIFI connection...")); int connectCounter = 0; while (WiFi.status() != WL_CONNECTED) @@ -173,7 +230,8 @@ void setup() } Serial.print("Connected to WiFi. IP:"); Serial.println(WiFi.localIP()); - + + Serial.println("Running version 1"); // todo // Session sessionManager.begin(); @@ -189,4 +247,5 @@ void loop() { sessionManager.iteration(); webSocketServer.iteration(); + checkWifi(); }