From 396e1f1cf9a638b12c02b85ccc9657dc7daf8ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20M=C3=BChl?= <31169771+Blueforcer@users.noreply.github.com> Date: Thu, 23 Mar 2023 22:11:46 +0100 Subject: [PATCH] 0.37 - add self updating function. You can start an update from onscreen menu --- docs/custom.md | 2 +- docs/onscreen.md | 10 ++- docs/quickstart.md | 2 +- lib/MatrixUI/MatrixDisplayUi.cpp | 1 - src/DisplayManager.cpp | 24 ++++++ src/DisplayManager.h | 3 + src/Globals.cpp | 2 +- src/MenuManager.cpp | 10 ++- src/PeripheryManager.cpp | 2 - src/ServerManager.cpp | 3 +- src/cert.h | 30 ++++++++ src/main.cpp | 23 +++--- src/updater.h | 124 +++++++++++++++++++++++++++++++ 13 files changed, 214 insertions(+), 22 deletions(-) create mode 100644 src/cert.h create mode 100644 src/updater.h diff --git a/docs/custom.md b/docs/custom.md index d18372d..de9e1e6 100644 --- a/docs/custom.md +++ b/docs/custom.md @@ -15,7 +15,7 @@ The JSON object has the following properties: | `rainbow` | boolean | Fades each letter in the text differently through the entire RGB spectrum. | false | | `duration` | number | Sets how long the page should be displayed. | 5 | | `color` | string | A color hex string for the text color. | "#FFFFFF" | -| `hold` | boolean | Set it to true, to hold your notification on top until you press the middle button or dismiss it via HomeAssistant. | false | +| `hold` | boolean | Set it to true, to hold your notification on top until you press the middle button or dismiss it via HomeAssistant. This key only belongs to notification. | false | | `sound` | string | The filename of your RTTTL ringtone file (without extension). | | | `pushIcon` | number | 0 = Icon doesn't move. 1 = Icon moves with text and will not appear again. 2 = Icon moves with text but appears again when the text starts to scroll again. | 0 | diff --git a/docs/onscreen.md b/docs/onscreen.md index ee0725f..95e4433 100644 --- a/docs/onscreen.md +++ b/docs/onscreen.md @@ -25,6 +25,12 @@ To change the color, use the left and right buttons to navigate through the avai #### SWITCH This setting determines whether the pages should automatically switch after the specified time. To save your setting, press and hold the middle button for 2 seconds. This will exit the menu and store your setting. + +#### T-SPEED +In this menu you can change the transisiton speed between apps. + +#### T_SPEED +In this menu, you can adjust the duration for which an app is displayed before switching to the next one. -#### REBOOT -This will reboot your clock :-) \ No newline at end of file +#### UPDATE +Here you can check and download a new firmware if available. diff --git a/docs/quickstart.md b/docs/quickstart.md index 06784c9..75be93f 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -1,6 +1,6 @@ # Quick start -1. :computer: Flashing. Connect your device to your PC or Mac and [use the online flahser](flasher.md) +1. :computer: Connect your device to your PC or Mac and [use the online flahser](flasher.md) 2. :signal_strength: After flashing, Awtrix will open an access point with the name "AWTRIX LIGHT". Connect with PW "12345678". 3. :mag: Open a browser and navigate to 192.168.4.1. Enter your WiFi information and reboot the clock. 4. :clock1: Your clock is accessible via http://awtrixlight.local/. diff --git a/lib/MatrixUI/MatrixDisplayUi.cpp b/lib/MatrixUI/MatrixDisplayUi.cpp index 51c8678..55baa2c 100644 --- a/lib/MatrixUI/MatrixDisplayUi.cpp +++ b/lib/MatrixUI/MatrixDisplayUi.cpp @@ -262,7 +262,6 @@ void MatrixDisplayUi::drawApp() y *= dir; x1 *= dir; y1 *= dir; - Serial.println(progress); bool FirstFrame = progress < 0.2; bool LastFrame = progress > 0.8; this->matrix->drawRect(x, y, x1, y1, matrix->Color(0, 0, 0)); diff --git a/src/DisplayManager.cpp b/src/DisplayManager.cpp index 8a24da5..30c7e20 100644 --- a/src/DisplayManager.cpp +++ b/src/DisplayManager.cpp @@ -390,6 +390,17 @@ void DisplayManager_::tick() } } +void DisplayManager_::clear() +{ + matrix.clear(); +} + +void DisplayManager_::show() +{ + matrix.show(); +} + + void DisplayManager_::leftButton() { if (!MenuManager.inMenu) @@ -512,4 +523,17 @@ void DisplayManager_::setNewSettings(String Payload) AUTO_TRANSITION = doc.containsKey("autotransition") ? doc["autotransition"] : AUTO_TRANSITION; applyAllSettings(); saveSettings(); +} + +void DisplayManager_::drawProgressBar(int cur, int total) +{ + matrix.clear(); + int progress = (cur * 100) / total; + char progressStr[5]; + snprintf(progressStr, 5, "%d%%", progress); // Formatieren des Prozentzeichens + printText(0, 6, progressStr, true, false); + int leds_for_progress = (progress * MATRIX_WIDTH * MATRIX_HEIGHT) / 100; + matrix.drawFastHLine(0, 7, MATRIX_WIDTH, matrix.Color(100, 100, 100)); + matrix.drawFastHLine(0, 7, leds_for_progress / MATRIX_HEIGHT, matrix.Color(0, 255, 0)); + matrix.show(); } \ No newline at end of file diff --git a/src/DisplayManager.h b/src/DisplayManager.h index e0a587b..1b9c346 100644 --- a/src/DisplayManager.h +++ b/src/DisplayManager.h @@ -26,6 +26,8 @@ public: static DisplayManager_ &getInstance(); void setup(); void tick(); + void clear(); + void show(); void applyAllSettings(); void rightButton(); void dismissNotify(); @@ -51,6 +53,7 @@ public: void setNewSettings(String Payload); void drawGIF(uint16_t x, uint16_t y, fs::File gifFile); void drawJPG(uint16_t x, uint16_t y, fs::File jpgFile); + void drawProgressBar(int cur, int total); }; extern DisplayManager_ &DisplayManager; diff --git a/src/Globals.cpp b/src/Globals.cpp index a4614d0..c88f61e 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -34,7 +34,7 @@ IPAddress gateway; IPAddress subnet; IPAddress primaryDNS; IPAddress secondaryDNS; -const char *VERSION = "0.36"; +const char *VERSION = "0.37"; String MQTT_HOST = ""; uint16_t MQTT_PORT = 1883; String MQTT_USER; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 80bef25..fb75cc2 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -4,6 +4,7 @@ #include #include #include +#include String menuText; int menuSelection; @@ -33,9 +34,10 @@ const char *menuItems[] = { "COLOR", "SWITCH", "T-SPEED", - "APPTIME"}; + "APPTIME", + "UPDATE"}; -byte menuItemCount = 6; +byte menuItemCount = 7; MenuState currentState = MainMenu; @@ -248,6 +250,10 @@ void MenuManager_::selectButton() { currentState = AppTimeMenu; } + else if (menuIndex == 6) // AppTIme + { + FirmwareVersionCheck(); + } } else if (currentState == StationSelection) { diff --git a/src/PeripheryManager.cpp b/src/PeripheryManager.cpp index b256d94..231e849 100644 --- a/src/PeripheryManager.cpp +++ b/src/PeripheryManager.cpp @@ -168,9 +168,7 @@ void PeripheryManager_::tick() { previousMillis_BatTempHum = currentMillis_BatTempHum; uint16_t ADCVALUE = analogRead(BATTERY_PIN); - Serial.println(ADCVALUE); BATTERY_PERCENT = min((int)map(ADCVALUE, 510, 665, 0, 100), 100); - Serial.println(BATTERY_PERCENT); CURRENT_LUX = (roundf(photocell.getSmoothedLux() * 1000) / 1000); sht31.readBoth(&CURRENT_TEMP, &CURRENT_HUM); CURRENT_TEMP -= 9.0; diff --git a/src/ServerManager.cpp b/src/ServerManager.cpp index df0daf1..562f1f4 100644 --- a/src/ServerManager.cpp +++ b/src/ServerManager.cpp @@ -213,4 +213,5 @@ void ServerManager_::loadSettings() else Serial.println(F("Configuration file not exist")); return; -} \ No newline at end of file +} + diff --git a/src/cert.h b/src/cert.h new file mode 100644 index 0000000..05b6977 --- /dev/null +++ b/src/cert.h @@ -0,0 +1,30 @@ +#ifndef CERT_H + +#define CERT_H + +//DigiCert root certificate has expiry date of 10 Nov 2031 +const char * rootCACertificate = \ +"-----BEGIN CERTIFICATE-----\n" \ +"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \ +"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \ +"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \ +"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \ +"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \ +"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \ +"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \ +"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \ +"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \ +"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \ +"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \ +"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \ +"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \ +"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \ +"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \ +"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \ +"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \ +"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \ +"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \ +"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \ +"-----END CERTIFICATE-----\n"; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4fb9f3d..be2b01c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,15 +1,15 @@ -/* ___ ___ ___ ___ - / /\ /__/\ ___ / /\ ___ /__/| - / /::\ _\_ \:\ / /\ / /::\ / /\ | |:| - / /:/\:\ /__/\ \:\ / /:/ / /:/\:\ / /:/ | |:| - / /:/~/::\ _\_ \:\ \:\ / /:/ / /:/~/:/ /__/::\ __|__|:| +/* ___ ___ ___ ___ + / /\ /__/\ ___ / /\ ___ /__/| + / /::\ _\_ \:\ / /\ / /::\ / /\ | |:| + / /:/\:\ /__/\ \:\ / /:/ / /:/\:\ / /:/ | |:| + / /:/~/::\ _\_ \:\ \:\ / /:/ / /:/~/:/ /__/::\ __|__|:| /__/:/ /:/\:\ /__/\ \:\ \:\ / /::\ /__/:/ /:/___ \__\/\:\__ /__/::::\____ \ \:\/:/__\/ \ \:\ \:\/:/ /__/:/\:\ \ \:\/:::::/ \ \:\/\ ~\~~\::::/ - \ \::/ \ \:\ \::/ \__\/ \:\ \ \::/~~~~ \__\::/ |~~|:|~~ - \ \:\ \ \:\/:/ \ \:\ \ \:\ /__/:/ | |:| - \ \:\ \ \::/ \__\/ \ \:\ \__\/ | |:| - \__\/ \__\/ \__\/ |__|/ + \ \::/ \ \:\ \::/ \__\/ \:\ \ \::/~~~~ \__\::/ |~~|:|~~ + \ \:\ \ \:\/:/ \ \:\ \ \:\ /__/:/ | |:| + \ \:\ \ \::/ \__\/ \ \:\ \__\/ | |:| + \__\/ \__\/ \__\/ |__|/ *************************************************************************** * * @@ -22,7 +22,7 @@ * 4.0 International License. * * * * More information: * - * https://github.com/Blueforcer/awtrix-light/blob/main/LICENSE.md * + * https://github.com/Blueforcer/awtrix-light/blob/main/LICENSE.md * * * * This firmware is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * @@ -30,7 +30,6 @@ * * ***************************************************************************/ - #include #include "DisplayManager.h" #include "PeripheryManager.h" @@ -65,6 +64,8 @@ void setup() loadSettings(); ServerManager.loadSettings(); DisplayManager.setup(); + DisplayManager.HSVtext(9, 6, VERSION, true); + delay(500); PeripheryManager.playBootSound(); xTaskCreatePinnedToCore(BootAnimation, "Task", 10000, NULL, 1, &taskHandle, 1); ServerManager.setup(); diff --git a/src/updater.h b/src/updater.h new file mode 100644 index 0000000..0799821 --- /dev/null +++ b/src/updater.h @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include "cert.h" +#include "DisplayManager.h" + +#define URL_fw_Version "https://raw.githubusercontent.com/Blueforcer/awtrix-light/main/version" +#define URL_fw_Bin "https://raw.githubusercontent.com/Blueforcer/awtrix-light/main/docs/flasher/firmware/firmware.bin" + +void update_started() +{ + +} + +void update_finished() +{ + Serial.println("CALLBACK: HTTP update process finished"); +} + +void update_progress(int cur, int total) +{ + DisplayManager.drawProgressBar(cur, total); +} + +void update_error(int err) +{ + DisplayManager.clear(); + DisplayManager.printText(0, 6, "FAIL", true, true); + DisplayManager.show(); +} + +void firmwareUpdate(void) +{ + WiFiClientSecure client; + client.setCACert(rootCACertificate); + + httpUpdate.onStart(update_started); + httpUpdate.onEnd(update_finished); + httpUpdate.onProgress(update_progress); + httpUpdate.onError(update_error); + + t_httpUpdate_return ret = httpUpdate.update(client, URL_fw_Bin); + switch (ret) + { + case HTTP_UPDATE_FAILED: + Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str()); + break; + + case HTTP_UPDATE_NO_UPDATES: + Serial.println("HTTP_UPDATE_NO_UPDATES"); + break; + + case HTTP_UPDATE_OK: + Serial.println("HTTP_UPDATE_OK"); + break; + } +} +int FirmwareVersionCheck(void) +{ + + DisplayManager.clear(); + DisplayManager.printText(0, 6, "CHECK", true, true); + DisplayManager.show(); + String payload; + int httpCode; + String fwurl = ""; + fwurl += URL_fw_Version; + fwurl += "?"; + fwurl += String(rand()); + Serial.println(fwurl); + WiFiClientSecure *client = new WiFiClientSecure; + + if (client) + { + client->setCACert(rootCACertificate); + + // Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is + HTTPClient https; + + if (https.begin(*client, fwurl)) + { // HTTPS + Serial.print("[HTTPS] GET...\n"); + // start connection and send HTTP header + delay(100); + httpCode = https.GET(); + delay(100); + if (httpCode == HTTP_CODE_OK) // if version received + { + payload = https.getString(); // save received version + } + else + { + Serial.print("error in downloading version file:"); + Serial.println(httpCode); + } + https.end(); + } + delete client; + } + + if (httpCode == HTTP_CODE_OK) // if version received + { + payload.trim(); + if (payload.equals(VERSION)) + { + Serial.printf("\nDevice already on latest firmware version:%s\n", VERSION); + DisplayManager.clear(); + DisplayManager.printText(0, 6, "NO UP :(", true, true); + DisplayManager.show(); + delay(1000); + return 0; + } + else + { + Serial.println(payload); + Serial.println("New firmware detected"); + DisplayManager.printText(0, 6, payload.c_str(), true, true); + firmwareUpdate(); + return 1; + } + } + return 0; +} \ No newline at end of file