Added market cap screen

This commit is contained in:
Djuri Baars 2023-11-11 10:00:06 +01:00
parent ff5754f2d1
commit 7d0d07e928
19 changed files with 144 additions and 73 deletions

View File

@ -63,8 +63,8 @@
<div class="progress-bar progress-bar-striped" style="width: {{ memUsage }}%">{{ memUsage }}%</div>
</div>
<div class="d-flex justify-content-between">
<div>Memory usage</div>
<div>{{ memFree }} / {{ memTotal }} kB</div>
<div>Memory free</div>
<div>{{ memFree }} / {{ memTotal }} KiB</div>
</div>
</div>
<hr>

View File

@ -1,6 +1,6 @@
import './helpers.js';
var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown"];
var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown", "Market Cap"];
toTime = (secs) => {
var hours = Math.floor(secs / (60 * 60));
@ -28,7 +28,7 @@ getBcStatus = () => {
var source = document.getElementById("entry-template").innerHTML;
var template = Handlebars.compile(source);
var context = { timerRunning: jsonData.timerRunning, memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100), memFree: (jsonData.espFreeHeap / 1000), memTotal: (jsonData.espHeapSize / 1000), uptime: toTime(jsonData.espUptime), currentScreen: jsonData.currentScreen, rendered: jsonData.rendered, data: jsonData.data, screens: screens, ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [] };
var context = { timerRunning: jsonData.timerRunning, memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100), memFree: (jsonData.espFreeHeap / 1024), memTotal: (jsonData.espHeapSize / 1024), uptime: toTime(jsonData.espUptime), currentScreen: jsonData.currentScreen, rendered: jsonData.rendered, data: jsonData.data, screens: screens, ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [] };
document.getElementById('output').innerHTML = template(context);

View File

@ -26,7 +26,7 @@ void setFgColor(int color)
void showSetupQr(const String &ssid, const String &password)
{
char displayIndex = 6;
uint displayIndex = 6;
const String text = "WIFI:S:" + ssid + ";T:WPA;P:" + password + ";;";

View File

@ -180,7 +180,9 @@ void setupPreferences()
{SCREEN_MSCW_TIME, "Sats per dollar"},
{SCREEN_BTC_TICKER, "Ticker"},
{SCREEN_TIME, "Time"},
{SCREEN_HALVING_COUNTDOWN, "Halving countdown"}};
{SCREEN_HALVING_COUNTDOWN, "Halving countdown"},
{SCREEN_MARKET_CAP, "Market Cap"}
};
#ifdef WITH_RGB_LED
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
@ -225,23 +227,21 @@ void handleScreenTasks(uint screen)
switch (currentScreen)
{
case SCREEN_BLOCK_HEIGHT:
if (blockNotifyTaskHandle)
{
vTaskResume(blockNotifyTaskHandle);
}
break;
case SCREEN_HALVING_COUNTDOWN:
if (blockNotifyTaskHandle)
vTaskResume(blockNotifyTaskHandle);
break;
case SCREEN_BTC_TICKER:
if (getPriceTaskHandle)
vTaskResume(getPriceTaskHandle);
break;
case SCREEN_MSCW_TIME:
if (getPriceTaskHandle)
vTaskResume(getPriceTaskHandle);
break;
case SCREEN_MARKET_CAP:
if (getPriceTaskHandle)
vTaskResume(getPriceTaskHandle);
if (blockNotifyTaskHandle)
vTaskResume(blockNotifyTaskHandle);
break;
case SCREEN_TIME:
if (minuteTaskHandle)
{
@ -388,7 +388,7 @@ void showNetworkSettings()
}
epdContent[NUM_SCREENS-2] = "RAM/Status";
epdContent[NUM_SCREENS-1] = String((int)round(ESP.getFreeHeap()/1000)) + "/" + (int)round(ESP.getHeapSize()/1000);
epdContent[NUM_SCREENS-1] = String((int)round(ESP.getFreeHeap()/1024)) + "/" + (int)round(ESP.getHeapSize()/1024);
CustomTextScreen::setText(epdContent);

43
src/lib/utils.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "utils.hpp";
double getSupplyAtBlock(uint 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;
}
std::string formatNumberWithSuffix(int64_t num) {
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;
if (num >= quadrillion) {
return std::to_string(num / quadrillion) + "Q";
} else if (num >= trillion) {
return std::to_string(num / trillion) + "T";
} else if (num >= billion) {
return std::to_string(num / billion) + "B";
} else if (num >= million) {
return std::to_string(num / million) + "M";
} else if (num >= thousand) {
return std::to_string(num / thousand) + "K";
} else {
return std::to_string(num);
}
}

6
src/lib/utils.hpp Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include "shared.hpp"
double getSupplyAtBlock(uint blockNr);
std::string formatNumberWithSuffix(int64_t num);

View File

@ -67,7 +67,7 @@ void setupWebserver()
/**
* @Api
* @Path("/api/status")
*/
*/
void onApiStatus(AsyncWebServerRequest *request)
{
AsyncResponseStream *response = request->beginResponseStream("application/json");
@ -110,7 +110,7 @@ void onApiStatus(AsyncWebServerRequest *request)
/**
* @Api
* @Path("/api/action/pause")
*/
*/
void onApiActionPause(AsyncWebServerRequest *request)
{
timerRunning = false;
@ -122,7 +122,7 @@ void onApiActionPause(AsyncWebServerRequest *request)
/**
* @Api
* @Path("/api/action/full_refresh")
*/
*/
void onApiFullRefresh(AsyncWebServerRequest *request)
{
@ -134,7 +134,7 @@ void onApiFullRefresh(AsyncWebServerRequest *request)
/**
* @Api
* @Path("/api/action/timer_restart")
*/
*/
void onApiActionTimerRestart(AsyncWebServerRequest *request)
{
// moment = millis();
@ -148,7 +148,7 @@ void onApiActionTimerRestart(AsyncWebServerRequest *request)
* @Api
* @Path("/api/action/update")
* @Parameter int rate Time in minutes
*/
*/
void onApiActionUpdate(AsyncWebServerRequest *request)
{
if (request->hasParam("rate"))
@ -167,10 +167,10 @@ void onApiActionUpdate(AsyncWebServerRequest *request)
* @Api
* @Method GET
* @Path("/api/settings")
*/
*/
void onApiSettingsGet(AsyncWebServerRequest *request)
{
StaticJsonDocument<768> root;
StaticJsonDocument<1536> root;
root["numScreens"] = NUM_SCREENS;
root["fgColor"] = getFgColor();
root["bgColor"] = getBgColor();
@ -212,7 +212,7 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
AsyncResponseStream *response = request->beginResponseStream("application/json");
serializeJson(root, *response);
request->send(response);
}

View File

@ -18,6 +18,7 @@
#include "screens/ticker.hpp"
#include "screens/time.hpp"
#include "screens/halvingcountdown.hpp"
#include "screens/market_cap.hpp"
#include "tasks/ha.hpp"
#include "tasks/epd.hpp"
@ -62,6 +63,7 @@ void setup()
BlockHeightScreen::init();
HalvingCountdownScreen::init();
TickerScreen::init();
MarketCapScreen::init();
#ifdef WITH_BUTTONS
setupButtonTask();

View File

@ -57,4 +57,8 @@ std::array<String, NUM_SCREENS> BlockHeightScreen::getEpdContent()
// std::copy(std::begin(BlockHeightScreen::epdContent), std::end(BlockHeightScreen::epdContent), std::begin(ret));
return ret;
}
uint BlockHeightScreen::getBlockNr() {
return blockNr;
}

View File

@ -17,4 +17,5 @@ public:
static void showScreen();
static void onNewBlock(uint blockNr);
static std::array<String, NUM_SCREENS> getEpdContent();
static uint getBlockNr();
};

View File

@ -0,0 +1,30 @@
#include "market_cap.hpp"
uint MarketCapScreen::satsPerDollar = 0;
std::array<String, NUM_SCREENS> MarketCapScreen::epdContent = {"", "", "", "", "", "", ""};
void MarketCapScreen::init()
{
// Dependent on price and blocks
MarketCapScreen::showScreen();
}
void MarketCapScreen::showScreen()
{
double supply = getSupplyAtBlock(BlockHeightScreen::getBlockNr());
int64_t marketCap = static_cast<std::int64_t>(supply * double(TickerScreen::getPrice()));
std::string priceString = "$" + formatNumberWithSuffix(marketCap);
priceString.insert(priceString.begin(), NUM_SCREENS - priceString.length(), ' ');
epdContent[0] = "USD/MCAP";
for (uint i = 1; i < NUM_SCREENS; i++)
{
MarketCapScreen::epdContent[i] = priceString[i];
}
}
std::array<String, NUM_SCREENS> MarketCapScreen::getEpdContent()
{
return MarketCapScreen::epdContent;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "base.hpp"
#include "config.h"
#include "shared.hpp"
#include "lib/utils.hpp"
#include "blockheight.hpp";
#include "ticker.hpp";
#include "tasks/epd.hpp"
class MarketCapScreen {
protected:
static uint satsPerDollar;
static std::array<String, NUM_SCREENS> epdContent;
public:
static void init();
static void showScreen();
static void onPriceUpdate(uint price);
static std::array<String, NUM_SCREENS> getEpdContent();
};

View File

@ -1,30 +0,0 @@
// #include "sats_per_dollar.hpp"
// uint SatsPerDollarScreen::satsPerDollar = 0;
// std::array<String, NUM_SCREENS> SatsPerDollarScreen::epdContent = { "", "", "", "", "", "", "" };
// void SatsPerDollarScreen::init() {
// SatsPerDollarScreen::satsPerDollar = int(round(1 / preferences.getFloat("btcPrice", 12345) * 10e7));
// setupGetPriceTask();
// SatsPerDollarScreen::showScreen();
// }
// void SatsPerDollarScreen::showScreen() {
// std::string satsPerDollarString = String(SatsPerDollarScreen::satsPerDollar).c_str();
// satsPerDollarString.insert(satsPerDollarString.begin(), 7 - satsPerDollarString.length(), ' ');
// epdContent[0] = "MSCW/TIME";
// for (uint i = 1; i < NUM_SCREENS; i++)
// {
// SatsPerDollarScreen::epdContent[i] = satsPerDollarString[i];
// }
// }
// void SatsPerDollarScreen::onPriceUpdate(uint price) {
// SatsPerDollarScreen::satsPerDollar = int(round(1 / float(price) * 10e7));
// SatsPerDollarScreen::showScreen();
// }
// std::array<String, NUM_SCREENS> SatsPerDollarScreen::getEpdContent() {
// return SatsPerDollarScreen::epdContent;
// }

View File

@ -1,17 +0,0 @@
// #pragma once
// #include "base.hpp"
// #include "config.h"
// #include "shared.hpp"
// #include "tasks/epd.hpp"
// class SatsPerDollarScreen {
// protected:
// static uint satsPerDollar;
// static std::array<String, NUM_SCREENS> epdContent;
// public:
// static void init();
// static void showScreen();
// static void onPriceUpdate(uint price);
// static std::array<String, NUM_SCREENS> getEpdContent();
// };

View File

@ -48,4 +48,8 @@ std::array<String, NUM_SCREENS> TickerScreen::getEpdContentSats() {
return epdContentSats;
}
uint TickerScreen::getPrice() {
return price;
}

View File

@ -18,4 +18,5 @@ public:
static void onPriceUpdate(uint price);
static std::array<String, NUM_SCREENS> getEpdContent();
static std::array<String, NUM_SCREENS> getEpdContentSats();
static uint getPrice();
};

View File

@ -55,9 +55,11 @@ const PROGMEM int SCREEN_MSCW_TIME = 1;
const PROGMEM int SCREEN_BTC_TICKER = 2;
const PROGMEM int SCREEN_TIME = 3;
const PROGMEM int SCREEN_HALVING_COUNTDOWN = 4;
const PROGMEM int SCREEN_MARKET_CAP = 5;
const PROGMEM int SCREEN_COUNTDOWN = 98;
const PROGMEM int SCREEN_CUSTOM = 99;
const PROGMEM int screens[5] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN };
const PROGMEM int screens[6] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP };
const uint screenCount = sizeof(screens) / sizeof(int);

View File

@ -192,6 +192,9 @@ void taskEpd(void *pvParameters)
case SCREEN_HALVING_COUNTDOWN:
epdContent = HalvingCountdownScreen::getEpdContent();
break;
case SCREEN_MARKET_CAP:
epdContent = MarketCapScreen::getEpdContent();
break;
case SCREEN_COUNTDOWN:
epdContent = CountdownScreen::getEpdContent();
break;
@ -325,7 +328,7 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
{
displays[epdIndex].init(0, false, 20); // Little longer reset duration because of MCP
displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
#ifndef USE_UNIVERSAL_PIN
resetSingleDisplay(epdIndex);
#endif

View File

@ -11,10 +11,12 @@
#include "screens/blockheight.hpp"
#include "screens/ticker.hpp"
#include "screens/time.hpp"
#include "screens/sats_per_dollar.hpp"
#include "screens/market_cap.hpp"
#include "screens/countdown.hpp"
#include "screens/custom_text.hpp"
#include "screens/halvingcountdown.hpp"
#ifdef USE_UNIVERSAL_PIN
#include <native_pin.hpp>
#include <mcp23x17_pin.hpp>