diff --git a/src/config.cpp b/src/config.cpp index 65ad555..c7eba0f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -43,6 +43,11 @@ void setupPreferences() { preferences.putString(SETTING_HOSTNAME_PREFIX, "oc"); } + + if (!preferences.isKey(SETTING_MEMPOOL_INSTANCE)) + { + preferences.putString(SETTING_MEMPOOL_INSTANCE, "https://mempool.space"); + } } void setupWifi() @@ -227,3 +232,22 @@ void OTAUpdateTask(void *pvParameters) { } } +char getCurrencyIcon() { + char ret; + const char* currency = preferences.getString(SETTING_CURRENCY).c_str(); + if (strcmp(currency, CURRENCY_USD) == 0) { + ret = ICON_DOLLAR; + } else if(strcmp(currency, CURRENCY_EUR) == 0) { + ret = ICON_EURO; + } + // break; + // case CURRENCY_GBP: + // ret = ICON_POUND; + // break; + // case CURRENCY_JPY: + // ret = ICON_YEN; + // break; + // } + + return ret; +} \ No newline at end of file diff --git a/src/config.hpp b/src/config.hpp index 1312aa6..c4936e4 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -21,3 +21,4 @@ void wakeModemSleep(); void setModemSleep(); bool inPowerSaveMode(); +char getCurrencyIcon(); \ No newline at end of file diff --git a/src/data.cpp b/src/data.cpp index b5f7eca..eb92216 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -1,10 +1,10 @@ #include "data.hpp" -const String mempoolInstance = "https://mempool.space"; +//const String mempoolInstance = "https://mempool.space"; -const String mempoolPriceApiUrl = mempoolInstance + "/api/v1/prices"; -const String mempoolBlockApiUrl = mempoolInstance + "/api/blocks/tip/height"; -const String mempoolFeeApiUrl = mempoolInstance + "/api/v1/fees/recommended"; +const String mempoolPriceApi = "/api/v1/prices"; +const String mempoolBlockApi = "/api/blocks/tip/height"; +const String mempoolFeeApi = "/api/v1/fees/recommended"; uint lastPrice; uint lastBlock; @@ -14,7 +14,7 @@ uint getPrice() HTTPClient http; // Send HTTP request to CoinGecko API - http.begin(mempoolPriceApiUrl); + http.begin(preferences.getString(SETTING_MEMPOOL_INSTANCE) + mempoolPriceApi); int httpCode = http.GET(); @@ -44,7 +44,7 @@ uint getBlock() HTTPClient http; // Send HTTP request to CoinGecko API - http.begin(mempoolBlockApiUrl); + http.begin(preferences.getString(SETTING_MEMPOOL_INSTANCE) + mempoolBlockApi); int httpCode = http.GET(); @@ -71,7 +71,7 @@ String getMempoolFees() HTTPClient http; // Send HTTP request to CoinGecko API - http.begin(mempoolFeeApiUrl); + http.begin(preferences.getString(SETTING_MEMPOOL_INSTANCE) + mempoolFeeApi); int httpCode = http.GET(); @@ -95,4 +95,83 @@ String getMempoolFees() http.end(); return ""; +} + +double getSupplyAtBlock(std::uint32_t blockNr) +{ + if (blockNr >= 33 * 210000) + { + return 20999999.9769; + } + + const int initialBlockReward = 50; // Initial block reward + const int halvingInterval = 210000; // Number of blocks before halving + + int halvingCount = blockNr / halvingInterval; + double totalBitcoinInCirculation = 0; + + for (int i = 0; i < halvingCount; ++i) + { + totalBitcoinInCirculation += halvingInterval * initialBlockReward * std::pow(0.5, i); + } + + totalBitcoinInCirculation += (blockNr % halvingInterval) * initialBlockReward * std::pow(0.5, halvingCount); + + return totalBitcoinInCirculation; +} + +String formatNumberWithSuffix(std::uint64_t num, int numCharacters) +{ + static char result[20]; // Adjust size as needed + const long long quadrillion = 1000000000000000LL; + const long long trillion = 1000000000000LL; + const long long billion = 1000000000; + const long long million = 1000000; + const long long thousand = 1000; + + double numDouble = (double)num; + int numDigits = (int)log10(num) + 1; + char suffix; + + if (num >= quadrillion || numDigits > 15) + { + numDouble /= quadrillion; + suffix = 'Q'; + } + else if (num >= trillion || numDigits > 12) + { + numDouble /= trillion; + suffix = 'T'; + } + else if (num >= billion || numDigits > 9) + { + numDouble /= billion; + suffix = 'B'; + } + else if (num >= million || numDigits > 6) + { + numDouble /= million; + suffix = 'M'; + } + else if (num >= thousand || numDigits > 3) + { + numDouble /= thousand; + suffix = 'K'; + } + else + { + sprintf(result, "%llu", (unsigned long long)num); + return result; + } + + // Add suffix + int len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix); + + // If there's room, add decimal places + if (len < numCharacters) + { + snprintf(result, sizeof(result), "%.*f%c", numCharacters - len - 1, numDouble, suffix); + } + + return result; } \ No newline at end of file diff --git a/src/data.hpp b/src/data.hpp index 9b2e363..176db2a 100644 --- a/src/data.hpp +++ b/src/data.hpp @@ -9,4 +9,6 @@ uint getPrice(); uint getBlock(); -String getMempoolFees(); \ No newline at end of file +String getMempoolFees(); +double getSupplyAtBlock(std::uint32_t blockNr); +String formatNumberWithSuffix(std::uint64_t num, int numCharacters); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 2b42fb5..3b111b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -114,9 +114,12 @@ void loop() rowContent = "NOT IMPL"; break; case LINE_HALVING_COUNTDOWN: + { icon = ICON_HOURGLASS; - rowContent = "NOT IMPL"; + uint currentBlock = getBlock(); + rowContent = 210000 - (currentBlock % 210000); break; + } case LINE_SATSPERUNIT: { icon = ICON_SATS; @@ -125,19 +128,32 @@ void loop() break; } case LINE_FIATPRICE: - icon = ICON_DOLLAR; + icon = getCurrencyIcon(); rowContent = getPrice(); break; case LINE_MARKETCAP: - icon = ICON_GLOBE; - rowContent = "NOT IMPL"; + { + icon = getCurrencyIcon(); + int64_t marketCap = static_cast(getSupplyAtBlock(getBlock()) * double(getPrice())); + rowContent = String(formatNumberWithSuffix(marketCap, 4)); break; + } case LINE_TIME: - rowContent = "NOT IMPL"; + { + icon = ICON_GLOBE; + char dateString[10]; + strftime(dateString, 10, "%H:%M:%S", &timeinfo); + rowContent = dateString; break; + } case LINE_DATE: - rowContent = "NOT IMPL"; + { + icon = ICON_GLOBE; + char dateString[10]; + strftime(dateString, 10, "%x", &timeinfo); + rowContent = dateString; break; + } default: rowContent = "DEFAULT"; } diff --git a/src/shared.hpp b/src/shared.hpp index b4a5b81..fff9a85 100644 --- a/src/shared.hpp +++ b/src/shared.hpp @@ -26,13 +26,13 @@ #define EPD_CLASS GxEPD2_290_T94 #define ROW1_FONT LibreFranklin_SemiBold15pt7b #define ROW1_ICONFONT orangeclock_icons14pt7b - #define ROW1_ICONWIDTH 27 + #define ROW1_ICONWIDTH 29 #define ROW2_FONT LibreFranklin_Bold25pt7b #define ROW2_ICONFONT orangeclock_icons25pt7b #define ROW2_ICONWIDTH 52 #define ROW3_FONT LibreFranklin_SemiBold15pt7b #define ROW3_ICONFONT orangeclock_icons14pt7b - #define ROW3_ICONWIDTH 27 + #define ROW3_ICONWIDTH 29 #define SETUPFONT LibreFranklin_SemiBold12pt7b #endif @@ -61,6 +61,7 @@ #define SETTING_ROW3_CONTENT "row3" #define SETTING_CURRENCY "currency" #define SETTING_HOSTNAME_PREFIX "hostnamePrefix" +#define SETTING_MEMPOOL_INSTANCE "mempoolInstance" const int LINE_BLOCKHEIGHT = 0; const int LINE_MEMPOOL_FEES = 1; diff --git a/src/webserver.cpp b/src/webserver.cpp index 18f6720..159b85b 100644 --- a/src/webserver.cpp +++ b/src/webserver.cpp @@ -3,7 +3,7 @@ AsyncWebServer server(80); const String uintSettings[] = {SETTING_ROW1_CONTENT, SETTING_ROW2_CONTENT, SETTING_ROW3_CONTENT}; -const String stringSettings[] = {SETTING_CURRENCY}; +const String stringSettings[] = {SETTING_CURRENCY,SETTING_MEMPOOL_INSTANCE}; const String boolSettings[] = {}; void setupWebserver() @@ -15,6 +15,9 @@ void setupWebserver() server.on("/api/status", HTTP_GET, onApiStatus); server.on("/api/settings", HTTP_GET, onApiSettingsGet); + server.on("/api/restart", HTTP_GET, onApiRestart); + server.on("/api/full_refresh", HTTP_GET, onApiFullRefresh); + AsyncCallbackJsonWebHandler *settingsPatchHandler = new AsyncCallbackJsonWebHandler("/api/json/settings", onApiSettingsPatch); server.addHandler(settingsPatchHandler); @@ -150,3 +153,21 @@ void onNotFound(AsyncWebServerRequest *request) request->send(404); } } + +void onApiRestart(AsyncWebServerRequest *request) { + request->send(200); + + delay(500); + + esp_restart(); +} + +/** + * @Api + * @Path("/api/full_refresh") + */ +void onApiFullRefresh(AsyncWebServerRequest *request) { + display.refresh(); + + request->send(200); +} \ No newline at end of file diff --git a/src/webserver.hpp b/src/webserver.hpp index 61a154d..30230de 100644 --- a/src/webserver.hpp +++ b/src/webserver.hpp @@ -13,6 +13,8 @@ void onApiStatus(AsyncWebServerRequest *request); void onApiSettingsGet(AsyncWebServerRequest *request); void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json); +void onApiFullRefresh(AsyncWebServerRequest *request); +void onApiRestart(AsyncWebServerRequest *request); void onIndex(AsyncWebServerRequest *request); void onNotFound(AsyncWebServerRequest *request); \ No newline at end of file