From efaab00fb41328100e3021ca8b5e4f57754e846a Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Wed, 8 May 2024 23:54:17 +0200 Subject: [PATCH] WebUI: Add German translation, switch to own price source --- data | 2 +- src/lib/config.cpp | 48 +++++++++++++++++---- src/lib/led_handler.cpp | 8 ++-- src/lib/price_notify.cpp | 92 +++++++++++++++++++++++++--------------- src/lib/shared.cpp | 10 +++++ src/lib/webserver.cpp | 5 ++- 6 files changed, 117 insertions(+), 48 deletions(-) create mode 100644 src/lib/shared.cpp diff --git a/data b/data index dcdf989..e47fc06 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit dcdf98964a42ccd83b2d2501bbed46a640bbc300 +Subproject commit e47fc066b0608132c44a35f7041be80b263adcff diff --git a/src/lib/config.cpp b/src/lib/config.cpp index eb420dc..893d773 100644 --- a/src/lib/config.cpp +++ b/src/lib/config.cpp @@ -41,7 +41,8 @@ void setup() if (mcp1.digitalRead(0) == LOW) { // Then loop forever to prevent anything else from writing to the screen - while (true) { + while (true) + { delay(1000); } } @@ -84,7 +85,7 @@ void tryImprovSetup() } } - // if (!preferences.getBool("wifiConfigured", false)) + // if (!preferences.getBool("wifiConfigured", false)) { queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG); @@ -130,13 +131,23 @@ void tryImprovSetup() const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password; + // Set the UNIX timestamp + time_t timestamp = LAST_BUILD_TIME; // Example timestamp: March 7, 2021 00:00:00 UTC + + // Convert the timestamp to a struct tm in UTC + struct tm *timeinfo = gmtime(×tamp); + + // Format the date + char formattedDate[20]; + strftime(formattedDate, sizeof(formattedDate), "%y-%m-%d\r\n%H:%M:%S", timeinfo); + std::array epdContent = { "Welcome!", "Bienvenidos!", "To setup\r\nscan QR or\r\nconnect\r\nmanually", "Para\r\nconfigurar\r\nescanear QR\r\no conectar\r\nmanualmente", explainText, - "*Hostname*:\r\n" + getMyHostname(), + "*Hostname*:\r\n" + getMyHostname() + "\r\n\r\n" + "*FW build date:*\r\n" + formattedDate, qrText}; setEpdContent(epdContent); }); @@ -311,6 +322,17 @@ void setupHardware() Serial.println(F("Error loading WebUI")); } + // if (!LittleFS.exists("/qr.txt")) + // { + // File f = LittleFS.open("/qr.txt", "w"); + + // if(f) { + + // } else { + // Serial.println(F("Can't write QR to FS")); + // } + // } + setupLeds(); WiFi.setHostname(getMyHostname().c_str()); @@ -665,17 +687,27 @@ String getMyHostname() return hostname; } -uint getLastTimeSync() { +uint getLastTimeSync() +{ return lastTimeSync; } #ifdef HAS_FRONTLIGHT -void setupFrontlight() { - flArray.begin(); +void setupFrontlight() +{ + if (!flArray.begin(PCA9685_MODE1_AUTOINCR, PCA9685_MODE2_INVERT)) + { + Serial.println(F("FL driver error")); + return; + } + Serial.println(F("FL driver active")); flArray.setFrequency(1000); flArray.setOutputEnablePin(PCA_OE_PIN); - - if (!preferences.isKey("flMaxBrightness")) { + flArray.setOutputEnable(true); + delay(1000); + flArray.setOutputEnable(false); + if (!preferences.isKey("flMaxBrightness")) + { preferences.putUInt("flMaxBrightness", 4095); } // Initialize all LEDs to off diff --git a/src/lib/led_handler.cpp b/src/lib/led_handler.cpp index 8efe6d9..5580451 100644 --- a/src/lib/led_handler.cpp +++ b/src/lib/led_handler.cpp @@ -339,7 +339,7 @@ void frontlightFadeInAll() { for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) { flArray.setPWM(ledPin, 0, dutyCycle); } - delay(flDelayTime); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); } } @@ -348,21 +348,21 @@ void frontlightFadeOutAll() { for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) { flArray.setPWM(ledPin, 0, dutyCycle); } - delay(flDelayTime); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); } } void frontlightFadeIn(uint num) { for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) { flArray.setPWM(num, 0, dutyCycle); - delay(flDelayTime); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); } } void frontlightFadeOut(uint num) { for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) { flArray.setPWM(num, 0, dutyCycle); - delay(flDelayTime); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); } } #endif \ No newline at end of file diff --git a/src/lib/price_notify.cpp b/src/lib/price_notify.cpp index 05eea96..0fe80d2 100644 --- a/src/lib/price_notify.cpp +++ b/src/lib/price_notify.cpp @@ -1,5 +1,6 @@ #include "price_notify.hpp" +const char *wsOwnServerPrice = "wss://ws.btclock.store/ws?assets=bitcoin"; const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin"; // const char* coinCapWsCert = R"(-----BEGIN CERTIFICATE----- @@ -35,17 +36,25 @@ const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin"; // WebsocketsClient client; esp_websocket_client_handle_t clientPrice = NULL; -uint currentPrice = 30000; +esp_websocket_client_config_t config; +uint currentPrice = 50000; unsigned long int lastPriceUpdate; bool priceNotifyInit = false; -void setupPriceNotify() { +void setupPriceNotify() +{ // currentPrice = preferences.get("lastPrice", 30000); - esp_websocket_client_config_t config = {.uri = wsServerPrice, - // .task_stack = (7*1024), - // .cert_pem = coinCapWsCert, - .user_agent = USER_AGENT}; + if (preferences.getBool("ownPriceSource", true)) + { + config = {.uri = wsOwnServerPrice, + .user_agent = USER_AGENT}; + } + else + { + config = {.uri = wsServerPrice, + .user_agent = USER_AGENT}; + } clientPrice = esp_websocket_client_init(&config); esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY, @@ -54,40 +63,46 @@ void setupPriceNotify() { } void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, - int32_t event_id, void *event_data) { + int32_t event_id, void *event_data) +{ esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data; - switch (event_id) { - case WEBSOCKET_EVENT_CONNECTED: - Serial.println(F("Connected to CoinCap.io WebSocket")); - priceNotifyInit = true; + switch (event_id) + { + case WEBSOCKET_EVENT_CONNECTED: + Serial.println("Connected to " + String(config.uri) + " WebSocket"); + priceNotifyInit = true; - break; - case WEBSOCKET_EVENT_DATA: - onWebsocketPriceMessage(data); - break; - case WEBSOCKET_EVENT_ERROR: - Serial.println(F("Price WS Connnection error")); - break; - case WEBSOCKET_EVENT_DISCONNECTED: - Serial.println(F("Price WS Connnection Closed")); - break; + break; + case WEBSOCKET_EVENT_DATA: + onWebsocketPriceMessage(data); + break; + case WEBSOCKET_EVENT_ERROR: + Serial.println(F("Price WS Connnection error")); + break; + case WEBSOCKET_EVENT_DISCONNECTED: + Serial.println(F("Price WS Connnection Closed")); + break; } } -void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) { +void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) +{ JsonDocument doc; deserializeJson(doc, (char *)event_data->data_ptr); - if (doc.containsKey("bitcoin")) { - if (currentPrice != doc["bitcoin"].as()) { + if (doc.containsKey("bitcoin")) + { + if (currentPrice != doc["bitcoin"].as()) + { uint minSecPriceUpd = preferences.getUInt( "minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE); uint currentTime = esp_timer_get_time() / 1000000; if (lastPriceUpdate == 0 || - (currentTime - lastPriceUpdate) > minSecPriceUpd) { + (currentTime - lastPriceUpdate) > minSecPriceUpd) + { // const unsigned long oldPrice = currentPrice; currentPrice = doc["bitcoin"].as(); preferences.putUInt("lastPrice", currentPrice); @@ -95,7 +110,8 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) { // if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) { if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || - getCurrentScreen() == SCREEN_MARKET_CAP)) { + getCurrentScreen() == SCREEN_MARKET_CAP)) + { WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0}; xQueueSend(workQueue, &priceUpdate, portMAX_DELAY); } @@ -105,7 +121,8 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) { } } -uint getLastPriceUpdate() { +uint getLastPriceUpdate() +{ return lastPriceUpdate; } @@ -113,17 +130,22 @@ uint getPrice() { return currentPrice; } void setPrice(uint newPrice) { currentPrice = newPrice; } -bool isPriceNotifyConnected() { - if (clientPrice == NULL) return false; +bool isPriceNotifyConnected() +{ + if (clientPrice == NULL) + return false; return esp_websocket_client_is_connected(clientPrice); } -bool getPriceNotifyInit() { +bool getPriceNotifyInit() +{ return priceNotifyInit; } -void stopPriceNotify() { - if (clientPrice == NULL) return; +void stopPriceNotify() +{ + if (clientPrice == NULL) + return; esp_websocket_client_close(clientPrice, pdMS_TO_TICKS(5000)); esp_websocket_client_stop(clientPrice); esp_websocket_client_destroy(clientPrice); @@ -131,9 +153,11 @@ void stopPriceNotify() { clientPrice = NULL; } -void restartPriceNotify() { +void restartPriceNotify() +{ stopPriceNotify(); - if (clientPrice == NULL) { + if (clientPrice == NULL) + { setupPriceNotify(); return; } diff --git a/src/lib/shared.cpp b/src/lib/shared.cpp new file mode 100644 index 0000000..e6acfab --- /dev/null +++ b/src/lib/shared.cpp @@ -0,0 +1,10 @@ +#include "shared.hpp" + +#ifdef TEST_SCREENS +uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24 +uint8_t output_row_mono_buffer[max_row_width / 8]; // buffer for at least one row of b/w bits +uint8_t output_row_color_buffer[max_row_width / 8]; // buffer for at least one row of color bits +uint8_t mono_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 b/w +uint8_t color_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 c/w +uint16_t rgb_palette_buffer[max_palette_pixels]; // palette buffer for depth <= 8 for buffered graphics, needed for 7-color display +#endif \ No newline at end of file diff --git a/src/lib/webserver.cpp b/src/lib/webserver.cpp index 230fae3..5e6877b 100644 --- a/src/lib/webserver.cpp +++ b/src/lib/webserver.cpp @@ -329,7 +329,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) { String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd", "mdnsEnabled", "otaEnabled", "stealFocus", "mcapBigChar", "useSatsSymbol", "useBlkCountdown", - "suffixPrice", "disableLeds"}; + "suffixPrice", "disableLeds", "ownPriceSource", "flAlwaysOn"}; for (String setting : boolSettings) { if (settings.containsKey(setting)) { @@ -425,10 +425,13 @@ void onApiSettingsGet(AsyncWebServerRequest *request) { root["hostname"] = getMyHostname(); root["ip"] = WiFi.localIP(); root["txPower"] = WiFi.getTxPower(); + root["ownPriceSource"] = preferences.getBool("ownPriceSource", true); #ifdef HAS_FRONTLIGHT root["hasFrontlight"] = true; root["flMaxBrightness"] = preferences.getUInt("flMaxBrightness", 4095); + root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", false); + #else root["hasFrontlight"] = false; #endif