From ff50acf913da8d8220ea79e110415dd6d18c521d Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Wed, 18 Sep 2024 02:00:10 +0200 Subject: [PATCH] Fix WebUI currency converter, reorganize some code --- data | 2 +- src/lib/block_notify.hpp | 1 + src/lib/button_handler.hpp | 1 + src/lib/config.cpp | 4 +- src/lib/nostr_notify.hpp | 1 + src/lib/ota.hpp | 1 + src/lib/screen_handler.cpp | 92 +------------------ src/lib/screen_handler.hpp | 12 +-- src/lib/timers.cpp | 86 ++++++++++++++++++ src/lib/timers.hpp | 22 +++++ src/lib/v2_notify.cpp | 180 ++++++++++++++++++++----------------- src/lib/v2_notify.hpp | 16 ++-- src/lib/webserver.cpp | 3 +- src/main.cpp | 2 +- 14 files changed, 228 insertions(+), 195 deletions(-) create mode 100644 src/lib/timers.cpp create mode 100644 src/lib/timers.hpp diff --git a/data b/data index 761c7f2..7d82b1e 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 761c7f2991d347e97e77470ea3bf5511d7a7e507 +Subproject commit 7d82b1e1a9014e80f725478333774f4d53e22134 diff --git a/src/lib/block_notify.hpp b/src/lib/block_notify.hpp index 0af7196..d5565eb 100644 --- a/src/lib/block_notify.hpp +++ b/src/lib/block_notify.hpp @@ -11,6 +11,7 @@ #include "lib/led_handler.hpp" #include "lib/screen_handler.hpp" +#include "lib/timers.hpp" #include "lib/shared.hpp" // using namespace websockets; diff --git a/src/lib/button_handler.hpp b/src/lib/button_handler.hpp index 03e1b36..9f28d33 100644 --- a/src/lib/button_handler.hpp +++ b/src/lib/button_handler.hpp @@ -4,6 +4,7 @@ #include "lib/screen_handler.hpp" #include "lib/shared.hpp" +#include "lib/timers.hpp" extern TaskHandle_t buttonTaskHandle; diff --git a/src/lib/config.cpp b/src/lib/config.cpp index cc50719..2898a31 100644 --- a/src/lib/config.cpp +++ b/src/lib/config.cpp @@ -404,7 +404,7 @@ void setupWebsocketClients(void *pvParameters) { if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE)) { - setupV2Notify(); + V2Notify::setupV2Notify(); } else { @@ -553,7 +553,7 @@ void setupHardware() { Serial.println(F("Found BH1750")); hasLuxSensor = true; - bh1750.begin(BH1750::CONTINUOUS_LOW_RES_MODE, 0x5C); + bh1750.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x5C); } else { diff --git a/src/lib/nostr_notify.hpp b/src/lib/nostr_notify.hpp index d64e3e9..045574d 100644 --- a/src/lib/nostr_notify.hpp +++ b/src/lib/nostr_notify.hpp @@ -12,6 +12,7 @@ #include "price_notify.hpp" #include "block_notify.hpp" +#include "lib/timers.hpp" void setupNostrNotify(bool asDatasource, bool zapNotify); diff --git a/src/lib/ota.hpp b/src/lib/ota.hpp index 516f9a1..44704f6 100644 --- a/src/lib/ota.hpp +++ b/src/lib/ota.hpp @@ -5,6 +5,7 @@ #include "lib/config.hpp" #include "lib/shared.hpp" +#include "lib/timers.hpp" #ifndef UPDATE_MESSAGE_HPP #define UPDATE_MESSAGE_HPP diff --git a/src/lib/screen_handler.cpp b/src/lib/screen_handler.cpp index 091a6e0..d1c6165 100644 --- a/src/lib/screen_handler.cpp +++ b/src/lib/screen_handler.cpp @@ -5,8 +5,7 @@ // TaskHandle_t timeUpdateTaskHandle; TaskHandle_t taskScreenRotateTaskHandle; TaskHandle_t workerTaskHandle; -esp_timer_handle_t screenRotateTimer; -esp_timer_handle_t minuteTimer; + std::array taskEpdContent = {}; std::string priceString; @@ -23,8 +22,6 @@ void workerTask(void *pvParameters) { while (1) { // Wait for a work item to be available in the queue if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) { - uint firstIndex = 0; - // Process the work item based on its type switch (receivedItem.type) { case TASK_BITAXE_UPDATE: { @@ -42,10 +39,7 @@ void workerTask(void *pvParameters) { case TASK_PRICE_UPDATE: { uint currency = getCurrentCurrency(); uint price = getPrice(currency); - // u_char priceSymbol = '$'; - // if (preferences.getBool("fetchEurPrice", DEFAULT_FETCH_EUR_PRICE)) { - // priceSymbol = '['; - // } + if (getCurrentScreen() == SCREEN_BTC_TICKER) { taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE)); } else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) { @@ -121,29 +115,6 @@ void taskScreenRotate(void *pvParameters) { } } -void IRAM_ATTR minuteTimerISR(void *arg) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - // vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken); - WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; - xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken); - - if (bitaxeFetchTaskHandle != NULL) { - vTaskNotifyGiveFromISR(bitaxeFetchTaskHandle, &xHigherPriorityTaskWoken); - } - - if (xHigherPriorityTaskWoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - -void IRAM_ATTR screenRotateTimerISR(void *arg) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken); - if (xHigherPriorityTaskWoken == pdTRUE) { - portYIELD_FROM_ISR(); - } -} - void setupTasks() { workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem)); @@ -159,65 +130,6 @@ void setupTasks() { setCurrentScreen(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN)); } -void setupTimeUpdateTimer(void *pvParameters) { - const esp_timer_create_args_t minuteTimerConfig = { - .callback = &minuteTimerISR, .name = "minute_timer"}; - - esp_timer_create(&minuteTimerConfig, &minuteTimer); - - time_t currentTime; - struct tm timeinfo; - time(¤tTime); - localtime_r(¤tTime, &timeinfo); - uint32_t secondsUntilNextMinute = 60 - timeinfo.tm_sec; - - if (secondsUntilNextMinute > 0) - vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000))); - - esp_timer_start_periodic(minuteTimer, usPerMinute); - - WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; - xQueueSend(workQueue, &timeUpdate, portMAX_DELAY); - // xTaskNotifyGive(timeUpdateTaskHandle); - - vTaskDelete(NULL); -} - -void setupScreenRotateTimer(void *pvParameters) { - const esp_timer_create_args_t screenRotateTimerConfig = { - .callback = &screenRotateTimerISR, .name = "screen_rotate_timer"}; - - esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer); - - if (preferences.getBool("timerActive", DEFAULT_TIMER_ACTIVE)) { - esp_timer_start_periodic(screenRotateTimer, - getTimerSeconds() * usPerSecond); - } - - vTaskDelete(NULL); -} - -uint getTimerSeconds() { return preferences.getUInt("timerSeconds", DEFAULT_TIMER_SECONDS); } - -bool isTimerActive() { return esp_timer_is_active(screenRotateTimer); } - -void setTimerActive(bool status) { - if (status) { - esp_timer_start_periodic(screenRotateTimer, - getTimerSeconds() * usPerSecond); - queueLedEffect(LED_EFFECT_START_TIMER); - preferences.putBool("timerActive", true); - } else { - esp_timer_stop(screenRotateTimer); - queueLedEffect(LED_EFFECT_PAUSE_TIMER); - preferences.putBool("timerActive", false); - } - - if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle); -} - -void toggleTimerActive() { setTimerActive(!isTimerActive()); } - uint getCurrentScreen() { return currentScreen; } void setCurrentScreen(uint newScreen) { diff --git a/src/lib/screen_handler.hpp b/src/lib/screen_handler.hpp index 91e824a..6c99a7c 100644 --- a/src/lib/screen_handler.hpp +++ b/src/lib/screen_handler.hpp @@ -16,9 +16,6 @@ extern TaskHandle_t workerTaskHandle; extern TaskHandle_t taskScreenRotateTaskHandle; -extern esp_timer_handle_t screenRotateTimer; -extern esp_timer_handle_t minuteTimer; - extern QueueHandle_t workQueue; typedef enum { @@ -42,21 +39,14 @@ void previousScreen(); void showSystemStatusScreen(); -void setupTimeUpdateTimer(void *pvParameters); -void setupScreenRotateTimer(void *pvParameters); -void IRAM_ATTR minuteTimerISR(void *arg); -void IRAM_ATTR screenRotateTimerISR(void *arg); // void taskPriceUpdate(void *pvParameters); // void taskBlockUpdate(void *pvParameters); // void taskTimeUpdate(void *pvParameters); void taskScreenRotate(void *pvParameters); -uint getTimerSeconds(); -bool isTimerActive(); -void setTimerActive(bool status); -void toggleTimerActive(); + void setupTasks(); void setCurrentCurrency(char currency); diff --git a/src/lib/timers.cpp b/src/lib/timers.cpp new file mode 100644 index 0000000..d84d358 --- /dev/null +++ b/src/lib/timers.cpp @@ -0,0 +1,86 @@ +#include "timers.hpp" + +esp_timer_handle_t screenRotateTimer; +esp_timer_handle_t minuteTimer; + +void setupTimeUpdateTimer(void *pvParameters) { + const esp_timer_create_args_t minuteTimerConfig = { + .callback = &minuteTimerISR, .name = "minute_timer"}; + + esp_timer_create(&minuteTimerConfig, &minuteTimer); + + time_t currentTime; + struct tm timeinfo; + time(¤tTime); + localtime_r(¤tTime, &timeinfo); + uint32_t secondsUntilNextMinute = 60 - timeinfo.tm_sec; + + if (secondsUntilNextMinute > 0) + vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000))); + + esp_timer_start_periodic(minuteTimer, usPerMinute); + + WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; + xQueueSend(workQueue, &timeUpdate, portMAX_DELAY); + // xTaskNotifyGive(timeUpdateTaskHandle); + + vTaskDelete(NULL); +} + +void setupScreenRotateTimer(void *pvParameters) { + const esp_timer_create_args_t screenRotateTimerConfig = { + .callback = &screenRotateTimerISR, .name = "screen_rotate_timer"}; + + esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer); + + if (preferences.getBool("timerActive", DEFAULT_TIMER_ACTIVE)) { + esp_timer_start_periodic(screenRotateTimer, + getTimerSeconds() * usPerSecond); + } + + vTaskDelete(NULL); +} + +uint getTimerSeconds() { return preferences.getUInt("timerSeconds", DEFAULT_TIMER_SECONDS); } + +bool isTimerActive() { return esp_timer_is_active(screenRotateTimer); } + +void setTimerActive(bool status) { + if (status) { + esp_timer_start_periodic(screenRotateTimer, + getTimerSeconds() * usPerSecond); + queueLedEffect(LED_EFFECT_START_TIMER); + preferences.putBool("timerActive", true); + } else { + esp_timer_stop(screenRotateTimer); + queueLedEffect(LED_EFFECT_PAUSE_TIMER); + preferences.putBool("timerActive", false); + } + + if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle); +} + +void toggleTimerActive() { setTimerActive(!isTimerActive()); } + +void IRAM_ATTR minuteTimerISR(void *arg) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + // vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken); + WorkItem timeUpdate = {TASK_TIME_UPDATE, 0}; + xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken); + + if (bitaxeFetchTaskHandle != NULL) { + vTaskNotifyGiveFromISR(bitaxeFetchTaskHandle, &xHigherPriorityTaskWoken); + } + + if (xHigherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} + +void IRAM_ATTR screenRotateTimerISR(void *arg) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +} \ No newline at end of file diff --git a/src/lib/timers.hpp b/src/lib/timers.hpp new file mode 100644 index 0000000..e543a9f --- /dev/null +++ b/src/lib/timers.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + +#include "lib/shared.hpp" +#include "lib/screen_handler.hpp" + +extern esp_timer_handle_t screenRotateTimer; +extern esp_timer_handle_t minuteTimer; + +void setupTimeUpdateTimer(void *pvParameters); +void setupScreenRotateTimer(void *pvParameters); + +void IRAM_ATTR minuteTimerISR(void *arg); +void IRAM_ATTR screenRotateTimerISR(void *arg); + +uint getTimerSeconds(); +bool isTimerActive(); +void setTimerActive(bool status); +void toggleTimerActive(); \ No newline at end of file diff --git a/src/lib/v2_notify.cpp b/src/lib/v2_notify.cpp index 13d302d..33104a5 100644 --- a/src/lib/v2_notify.cpp +++ b/src/lib/v2_notify.cpp @@ -1,41 +1,51 @@ #include "v2_notify.hpp" -WebSocketsClient webSocket; -TaskHandle_t v2NotifyTaskHandle; +using namespace V2Notify; -void setupV2Notify() +namespace V2Notify { - String hostname = "ws.btclock.dev"; - if ( preferences.getBool("stagingSource", DEFAULT_STAGING_SOURCE)) { - Serial.println(F("Connecting to V2 staging source")); - hostname = "ws-staging.btclock.dev"; - } else { - Serial.println(F("Connecting to V2 source")); + WebSocketsClient webSocket; + + TaskHandle_t v2NotifyTaskHandle; + + void setupV2Notify() + { + String hostname = "ws.btclock.dev"; + if (preferences.getBool("stagingSource", DEFAULT_STAGING_SOURCE)) + { + Serial.println(F("Connecting to V2 staging source")); + hostname = "ws-staging.btclock.dev"; + } + else + { + Serial.println(F("Connecting to V2 source")); + } + + webSocket.beginSSL(hostname, 443, "/api/v2/ws"); + webSocket.onEvent(V2Notify::onWebsocketV2Event); + webSocket.setReconnectInterval(5000); + webSocket.enableHeartbeat(15000, 3000, 2); + + V2Notify::setupV2NotifyTask(); } - webSocket.beginSSL(hostname, 443, "/api/v2/ws"); - webSocket.onEvent(onWebsocketV2Event); - webSocket.setReconnectInterval(5000); - webSocket.enableHeartbeat(15000, 3000, 2); - - setupV2NotifyTask(); -} - -void onWebsocketV2Event(WStype_t type, uint8_t * payload, size_t length) { - switch(type) { - case WStype_DISCONNECTED: - Serial.printf("[WSc] Disconnected!\n"); - break; - case WStype_CONNECTED: + void onWebsocketV2Event(WStype_t type, uint8_t *payload, size_t length) + { + switch (type) { - Serial.printf("[WSc] Connected to url: %s\n", payload); + case WStype_DISCONNECTED: + Serial.printf("[WSc] Disconnected!\n"); + break; + case WStype_CONNECTED: + { + Serial.printf("[WSc] Connected to url: %s\n", payload); JsonDocument response; response["type"] = "subscribe"; response["eventType"] = "blockfee"; size_t responseLength = measureMsgPack(response); - uint8_t* buffer = new uint8_t[responseLength]; + uint8_t *buffer = new uint8_t[responseLength]; serializeMsgPack(response, buffer, responseLength); webSocket.sendBIN(buffer, responseLength); delete[] buffer; @@ -62,83 +72,89 @@ void onWebsocketV2Event(WStype_t type, uint8_t * payload, size_t length) { { currenciesArray.add(str); } - -// response["currencies"] = currenciesArray; + + // response["currencies"] = currenciesArray; responseLength = measureMsgPack(response); buffer = new uint8_t[responseLength]; serializeMsgPack(response, buffer, responseLength); webSocket.sendBIN(buffer, responseLength); - break; + break; } - case WStype_TEXT: - Serial.printf("[WSc] get text: %s\n", payload); + case WStype_TEXT: + Serial.printf("[WSc] get text: %s\n", payload); - // send message to server - // webSocket.sendTXT("message here"); - break; - case WStype_BIN: + // send message to server + // webSocket.sendTXT("message here"); + break; + case WStype_BIN: { JsonDocument doc; DeserializationError error = deserializeMsgPack(doc, payload, length); - handleV2Message(doc); - break; + V2Notify::handleV2Message(doc); + break; } - case WStype_ERROR: - case WStype_FRAGMENT_TEXT_START: - case WStype_FRAGMENT_BIN_START: - case WStype_FRAGMENT: + case WStype_ERROR: + case WStype_FRAGMENT_TEXT_START: + case WStype_FRAGMENT_BIN_START: + case WStype_FRAGMENT: case WStype_PING: case WStype_PONG: - case WStype_FRAGMENT_FIN: - break; - } -} - -void handleV2Message(JsonDocument doc) { - if (doc.containsKey("blockheight")) - { - uint newBlockHeight = doc["blockheight"].as(); - - if (newBlockHeight == getBlockHeight()) { - return; + case WStype_FRAGMENT_FIN: + break; + } } - processNewBlock(newBlockHeight); - } - else if (doc.containsKey("blockfee")) - { - uint medianFee = doc["blockfee"].as(); + void handleV2Message(JsonDocument doc) + { + if (doc.containsKey("blockheight")) + { + uint newBlockHeight = doc["blockheight"].as(); - processNewBlockFee(medianFee); - } else if (doc.containsKey("price")) - { + if (newBlockHeight == getBlockHeight()) + { + return; + } - // Iterate through the key-value pairs of the "price" object - for (JsonPair kv : doc["price"].as()) { - const char* currency = kv.key().c_str(); - uint newPrice = kv.value().as(); - - processNewPrice(newPrice, getCurrencyChar(currency)); + processNewBlock(newBlockHeight); + } + else if (doc.containsKey("blockfee")) + { + uint medianFee = doc["blockfee"].as(); - } - } -} + processNewBlockFee(medianFee); + } + else if (doc.containsKey("price")) + { -void taskV2Notify(void *pvParameters) { - for(;;) { - webSocket.loop(); - vTaskDelay(10 / portTICK_PERIOD_MS); + // Iterate through the key-value pairs of the "price" object + for (JsonPair kv : doc["price"].as()) + { + const char *currency = kv.key().c_str(); + uint newPrice = kv.value().as(); + + processNewPrice(newPrice, getCurrencyChar(currency)); + } + } } -} -void setupV2NotifyTask() { - xTaskCreate(taskV2Notify, "v2Notify", (6 * 1024), NULL, tskIDLE_PRIORITY, - &v2NotifyTaskHandle); + void taskV2Notify(void *pvParameters) + { + for (;;) + { + webSocket.loop(); + vTaskDelay(10 / portTICK_PERIOD_MS); + } + } -} + void setupV2NotifyTask() + { + xTaskCreate(V2Notify::taskV2Notify, "v2Notify", (6 * 1024), NULL, tskIDLE_PRIORITY, + &V2Notify::v2NotifyTaskHandle); + } -bool isV2NotifyConnected() -{ - return webSocket.isConnected(); -} + bool isV2NotifyConnected() + { + return webSocket.isConnected(); + } +} \ No newline at end of file diff --git a/src/lib/v2_notify.hpp b/src/lib/v2_notify.hpp index d3e4907..21a74ba 100644 --- a/src/lib/v2_notify.hpp +++ b/src/lib/v2_notify.hpp @@ -8,16 +8,18 @@ #include "lib/screen_handler.hpp" -extern TaskHandle_t v2NotifyTaskHandle; +namespace V2Notify { + extern TaskHandle_t v2NotifyTaskHandle; -void setupV2NotifyTask(); -void taskV2Notify(void *pvParameters); + void setupV2NotifyTask(); + void taskV2Notify(void *pvParameters); -void setupV2Notify(); -void onWebsocketV2Event(WStype_t type, uint8_t * payload, size_t length); -void handleV2Message(JsonDocument doc); + void setupV2Notify(); + void onWebsocketV2Event(WStype_t type, uint8_t * payload, size_t length); + void handleV2Message(JsonDocument doc); -bool isV2NotifyConnected(); + bool isV2NotifyConnected(); +} // void stopV2Notify(); // void restartV2Notify(); // bool getPriceNotifyInit(); diff --git a/src/lib/webserver.cpp b/src/lib/webserver.cpp index 801c286..88c40e4 100644 --- a/src/lib/webserver.cpp +++ b/src/lib/webserver.cpp @@ -256,9 +256,10 @@ JsonDocument getStatusObject() // root["espPsramSize"] = ESP.getPsramSize(); JsonObject conStatus = root["connectionStatus"].to(); + conStatus["price"] = isPriceNotifyConnected(); conStatus["blocks"] = isBlockNotifyConnected(); - conStatus["V2"] = isV2NotifyConnected(); + conStatus["V2"] = V2Notify::isV2NotifyConnected(); conStatus["nostr"] = nostrConnected(); diff --git a/src/main.cpp b/src/main.cpp index 0839e9d..908f155 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,7 +51,7 @@ extern "C" void app_main() if (hasLightLevel()) { if (preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE) != 0) { - if (hasLightLevel() && getLightLevel() == 0) + if (hasLightLevel() && getLightLevel() <= 2) { if (frontlightIsOn()) { frontlightFadeOutAll();