diff --git a/icons/update.png b/icons/update.png new file mode 100644 index 0000000..9ea00f4 Binary files /dev/null and b/icons/update.png differ diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index bb71673..4bdb903 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -119,6 +119,7 @@ set(headers icons/scan.h icons/settings.h icons/unchecked.h + icons/update.h icons/wifi.h menudisplay.h menuitem.h diff --git a/main/displays/menus/mainmenu.h b/main/displays/menus/mainmenu.h index e32cb3f..4beed43 100644 --- a/main/displays/menus/mainmenu.h +++ b/main/displays/menus/mainmenu.h @@ -15,6 +15,7 @@ #include "icons/settings.h" #include "icons/lock.h" #include "icons/demos.h" +#include "icons/update.h" #include "icons/poweroff.h" #include "icons/reboot.h" @@ -31,6 +32,7 @@ class SettingsMenu; class Lockscreen; class MosfetsMenu; class DemosMenu; +class UpdateDisplay; class PoweroffDisplay; class DebugMenu; } // namespace @@ -62,6 +64,7 @@ public: constructMenuItem, SwitchScreenAction>>(); #endif constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::demos>>>(); + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::update>>>(); constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::poweroff>>>(); constructMenuItem, RebootAction, StaticMenuItemIcon<&icons::reboot>>>(); constructMenuItem, SwitchScreenAction>>(); diff --git a/main/displays/updatedisplay.h b/main/displays/updatedisplay.h index 36e1811..4367e25 100644 --- a/main/displays/updatedisplay.h +++ b/main/displays/updatedisplay.h @@ -4,6 +4,9 @@ #include #include +// esp-idf includes +#include + // 3rdparty lib includes #ifdef FEATURE_OTA #include @@ -17,51 +20,32 @@ #include "texts.h" #include "widgets/label.h" #include "widgets/progressbar.h" -#include "modes/ignoreinputmode.h" +#include "ota.h" namespace { -class StatusDisplay; +class MainMenu; } namespace { #ifdef FEATURE_OTA -class UpdateDisplay : public Display, public DummyBack +class UpdateDisplay : public Display, public BackActionInterface> { public: - UpdateDisplay(const std::string &title); - UpdateDisplay(std::string &&title); - void start() override; void initScreen() override; void redraw() override; void confirm() override; -public: - bool m_finished; - unsigned int m_progress; - unsigned int m_total; - private: - const std::string m_title; - - Label m_progressLabel{20, 150}; + Label m_statusLabel{120, 75}; + Label m_progressLabel{120, 100}; + Label m_totalLabel{120, 125}; ProgressBar m_progressBar{20, 200, 200, 10, 0, 100}; }; -UpdateDisplay::UpdateDisplay(const std::string &title) : - m_title{title} -{} - -UpdateDisplay::UpdateDisplay(std::string &&title) : - m_title{std::move(title)} -{} - void UpdateDisplay::start() { - m_finished = false; - m_progress = 0; - m_total = 1; } void UpdateDisplay::initScreen() @@ -70,29 +54,59 @@ void UpdateDisplay::initScreen() tft.setTextFont(4); tft.setTextColor(TFT_YELLOW); - tft.drawString(m_title.c_str(), 5, 5, 4); + tft.drawString(TEXT_UPDATE, 5, 5, 4); tft.fillRect(0, 34, tft.width(), 3, TFT_WHITE); tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.drawString("Progress:", 20, 125); + tft.drawString("Status:", 20, m_statusLabel.y()); + m_statusLabel.start(); + + tft.drawString("Progress:", 20, m_progressLabel.y()); m_progressLabel.start(); + tft.drawString("Total:", 20, m_totalLabel.y()); + m_totalLabel.start(); + m_progressBar.start(); } void UpdateDisplay::redraw() { - m_progressLabel.redraw(fmt::format("{}/{}", m_progress, m_total)); + if (asyncOta) + { + m_statusLabel.redraw(toString(asyncOta->status())); + const auto progress = asyncOta->progress(); + m_progressLabel.redraw(std::to_string(progress)); + if (const auto totalSize = asyncOta->totalSize()) + { + m_totalLabel.redraw(std::to_string(*totalSize)); + m_progressBar.redraw(float(progress) / *totalSize * 100); + } + else + { + m_totalLabel.clear(); + m_progressBar.redraw(0); + } + } + else + { + m_statusLabel.clear(); + m_progressLabel.clear(); + m_totalLabel.clear(); - m_progressBar.redraw(float(m_progress) / m_total * 100.f); + m_progressBar.redraw(0); + } } void UpdateDisplay::confirm() { - if (m_finished) - switchScreen(); + //if (m_finished) + // switchScreen(); + + if (const auto result = triggerOta(stringSettings.otaUrl); !result) + ESP_LOGE("BOBBY", "triggerOta() failed with %.*s", result.error().size(), result.error().data()); } #endif } diff --git a/main/icons/update.h b/main/icons/update.h new file mode 100644 index 0000000..06214aa --- /dev/null +++ b/main/icons/update.h @@ -0,0 +1,46 @@ +#pragma once + +#include "icon.h" + +namespace { +namespace icons { +const Icon<24, 24> update{{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0010 (16) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0020 (32) pixels + 0x0000, 0x1CC1, 0x1620, 0x0E00, 0x0DA0, 0x0D40, 0x2581, 0x1CE1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0030 (48) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1500, 0x0E60, 0x0E20, 0x0DA0, 0x0D40, 0x2581, 0x1C41, // 0x0040 (64) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0050 (80) pixels + 0x0C60, 0x1540, 0x0E60, 0x0E00, 0x0D80, 0x0D40, 0x25A1, 0x1C81, 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0060 (96) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C60, 0x1D61, 0x2681, 0x0E00, 0x0D80, 0x0D40, 0x2DA1, 0x1C21, // 0x0070 (112) pixels + 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0080 (128) pixels + 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D60, 0x0D20, 0x2DA2, 0x1C21, 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0090 (144) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D60, 0x0D20, 0x2DA2, 0x1BE1, // 0x00A0 (160) pixels + 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00B0 (176) pixels + 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D40, 0x0D20, 0x2DA2, 0x1BE1, 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00C0 (192) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D40, 0x0D20, 0x2DA2, 0x1BE1, // 0x00D0 (208) pixels + 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00E0 (224) pixels + 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D40, 0x0D20, 0x2DA2, 0x1BE1, 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x00F0 (240) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C80, 0x25A1, 0x2EA1, 0x0E00, 0x0D20, 0x0D20, 0x2DA2, 0x1BE1, // 0x0100 (256) pixels + 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0110 (272) pixels + 0x0C60, 0x25A0, 0x2EA1, 0x0E00, 0x0D20, 0x0D20, 0x2DA2, 0x1BE1, 0x0DA0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0120 (288) pixels + 0x0000, 0x0000, 0x0000, 0x2403, 0x03E0, 0x0420, 0x0440, 0x0460, 0x2463, 0x25A1, 0x26A1, 0x0E00, 0x0D20, 0x0D20, 0x2DC2, 0x1461, // 0x0130 (304) pixels + 0x14A0, 0x1460, 0x1480, 0x1480, 0x0D41, 0x0E80, 0x0000, 0x0000, 0x0000, 0x0000, 0x1381, 0x34C4, 0x3662, 0x3682, 0x36A2, 0x36A1, // 0x0140 (320) pixels + 0x3E44, 0x3682, 0x26A1, 0x0E00, 0x0D20, 0x0D20, 0x1D81, 0x0D61, 0x14E0, 0x1500, 0x1540, 0x1560, 0x15C2, 0x1582, 0x16C0, 0x0000, // 0x0150 (336) pixels + 0x0000, 0x0000, 0x0000, 0x2C83, 0x46C3, 0x37E1, 0x2FE0, 0x2FE0, 0x2780, 0x1F00, 0x1680, 0x0E00, 0x0D20, 0x0D20, 0x0D60, 0x0D80, // 0x0160 (352) pixels + 0x0DC0, 0x0E00, 0x0E40, 0x1660, 0x1CE1, 0x1DA1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C41, 0x4723, 0x2FE1, 0x1FE0, // 0x0170 (368) pixels + 0x1F60, 0x1700, 0x0E80, 0x0E00, 0x0D20, 0x0D20, 0x0D60, 0x0D80, 0x0DC0, 0x0E00, 0x1620, 0x1520, 0x1540, 0x0E40, 0x0000, 0x0000, // 0x0180 (384) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C61, 0x3EE3, 0x37E1, 0x1F60, 0x1700, 0x0E80, 0x0E00, 0x0D20, 0x0D20, 0x0D60, 0x0D80, // 0x0190 (400) pixels + 0x0DC0, 0x1600, 0x14E1, 0x14A1, 0x0E40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x24C1, 0x3EC3, // 0x01A0 (416) pixels + 0x2781, 0x1700, 0x0E80, 0x0E00, 0x0D20, 0x0D20, 0x0D60, 0x0D80, 0x15E0, 0x1481, 0x14E1, 0x0E20, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01B0 (432) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1C81, 0x3EE3, 0x2701, 0x0E80, 0x0E00, 0x0D20, 0x0D20, 0x0D60, 0x15A0, // 0x01C0 (448) pixels + 0x14C1, 0x14C1, 0x0DC0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01D0 (464) pixels + 0x1481, 0x3643, 0x26A1, 0x0E00, 0x0D40, 0x0D20, 0x1580, 0x1481, 0x1441, 0x0DC0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x01E0 (480) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1CC1, 0x3602, 0x1E20, 0x0D40, 0x0D20, 0x1421, 0x1481, // 0x01F0 (496) pixels + 0x0D80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0200 (512) pixels + 0x0000, 0x0000, 0x14A0, 0x35E3, 0x1D61, 0x1441, 0x1461, 0x0D20, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0210 (528) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1480, 0x2CE3, 0x0BE0, 0x0D20, 0x0000, // 0x0220 (544) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0230 (560) pixels + 0x0000, 0x0000, 0x0000, 0x0000, 0x0B40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0240 (576) pixels +}}; +} +} diff --git a/main/ota.h b/main/ota.h index 0eb9c8c..233fca5 100644 --- a/main/ota.h +++ b/main/ota.h @@ -1,49 +1,52 @@ #pragma once +// 3rdparty lib includes #ifdef FEATURE_OTA #include #endif +#include -#include "screens.h" -#include "globals.h" -#include "displays/updatedisplay.h" +// local includes namespace { #ifdef FEATURE_OTA +cpputils::DelayedConstruction asyncOta; +bool asyncOtaTaskStarted{}; + void initOta() { -// ArduinoOTA -// .onStart([]() { -// std::string type; -// switch (ArduinoOTA.getCommand()) -// { -// case U_FLASH: type = "sketch"; break; -// case U_SPIFFS: type = "filesystem"; break; -// default: type = "unknown"; -// } -// switchScreenImpl("Updating " + type); -// }) -// .onEnd([]() { -// ((UpdateDisplay*)currentDisplay.get())->m_finished = true; -// ((UpdateDisplay*)currentDisplay.get())->redraw(); -// }) -// .onProgress([](unsigned int progress, unsigned int total) { -// ((UpdateDisplay*)currentDisplay.get())->m_progress = progress; -// ((UpdateDisplay*)currentDisplay.get())->m_total = total; -// ((UpdateDisplay*)currentDisplay.get())->redraw(); -// }) -// .onError([](ota_error_t error) { -// ((UpdateDisplay*)currentDisplay.get())->m_error = error; -// ((UpdateDisplay*)currentDisplay.get())->m_errorValid = true; -// ((UpdateDisplay*)currentDisplay.get())->redraw(); -// }); - -// ArduinoOTA.begin(); } void handleOta() { -// ArduinoOTA.handle(); + if (asyncOta) + asyncOta->update(); +} + +tl::expected triggerOta(std::string_view url) +{ + ESP_LOGI(TAG, "%.*s", url.size(), url.data()); + + if (!asyncOta) + asyncOta.construct(); + + if (!asyncOtaTaskStarted) + { + if (const auto result = asyncOta->startTask(); !result) + { + ESP_LOGE(TAG, "starting OTA task failed: %.*s", result.error().size(), result.error().data()); + return tl::make_unexpected(fmt::format("starting OTA task failed: {}", result.error())); + } + + asyncOtaTaskStarted = true; + } + + if (const auto result = asyncOta->trigger(url, {}, {}, {}); !result) + return tl::make_unexpected(std::move(result).error()); + + wifi_stack::delete_scan_result(); + + return {}; } #endif } diff --git a/main/presets.h b/main/presets.h index edbf354..0b43f7d 100644 --- a/main/presets.h +++ b/main/presets.h @@ -231,6 +231,9 @@ StringSettings makeDefaultStringSettings() }, #ifdef FEATURE_CLOUD .cloudUrl = {}, +#endif +#ifdef FEATURE_OTA + .otaUrl = {}, #endif }; } diff --git a/main/stringsettings.h b/main/stringsettings.h index f8241e8..53c8cdf 100644 --- a/main/stringsettings.h +++ b/main/stringsettings.h @@ -18,6 +18,10 @@ struct StringSettings std::string cloudUrl; #endif +#ifdef FEATURE_OTA + std::string otaUrl; +#endif + template void executeForEveryCommonSetting(T &&callable); @@ -53,6 +57,10 @@ void StringSettings::executeForEveryCommonSetting(T &&callable) #ifdef FEATURE_CLOUD callable("cloudUrl", cloudUrl); #endif + +#ifdef FEATURE_OTA + callable("otaUrl", otaUrl); +#endif } template diff --git a/main/texts.h b/main/texts.h index 9f7a410..9868126 100644 --- a/main/texts.h +++ b/main/texts.h @@ -79,6 +79,7 @@ constexpr char TEXT_SETTINGS[] = "Settings"; constexpr char TEXT_LOCKVEHICLE[] = "Lock vehicle"; constexpr char TEXT_MOSFETS[] = "Mosfets"; constexpr char TEXT_DEMOS[] = "Demos"; +constexpr char TEXT_UPDATE[] = "Update"; constexpr char TEXT_POWEROFF[] = "Poweroff"; constexpr char TEXT_REBOOT[] = "Reboot"; constexpr char TEXT_DEBUG[] = "Debug";