Add Mow mode notation and setting
Some checks failed
BTClock CI / build (push) Failing after 30s
BTClock CI / merge (map[name:btclock_rev_b version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:btclock_v8 version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 29epd) (push) Has been skipped
BTClock CI / release (push) Has been skipped
Some checks failed
BTClock CI / build (push) Failing after 30s
BTClock CI / merge (map[name:btclock_rev_b version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:btclock_v8 version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 213epd) (push) Has been skipped
BTClock CI / merge (map[name:lolin_s3_mini version:esp32s3], 29epd) (push) Has been skipped
BTClock CI / release (push) Has been skipped
This commit is contained in:
parent
239297c26d
commit
d37307cccf
10 changed files with 124 additions and 15 deletions
2
data
2
data
|
@ -1 +1 @@
|
||||||
Subproject commit 5066032a55b5436ec5c888cf0eb91bdc9e71bea0
|
Subproject commit d74e9dab60772ef11f9b033cfe982d216a9c95ee
|
|
@ -67,13 +67,13 @@ char getCurrencyChar(const std::string& input)
|
||||||
return CURRENCY_USD; // Assuming USD is the default for unknown inputs
|
return CURRENCY_USD; // Assuming USD is the default for unknown inputs
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat)
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currencySymbol, bool useSuffixFormat, bool mowMode)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> ret;
|
std::array<std::string, NUM_SCREENS> ret;
|
||||||
std::string priceString;
|
std::string priceString;
|
||||||
if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat)
|
if (std::to_string(price).length() >= NUM_SCREENS || useSuffixFormat)
|
||||||
{
|
{
|
||||||
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, NUM_SCREENS - 2);
|
priceString = getCurrencySymbol(currencySymbol) + formatNumberWithSuffix(price, NUM_SCREENS - 2, mowMode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ const std::string CURRENCY_CODE_JPY = "JPY";
|
||||||
const std::string CURRENCY_CODE_AUD = "AUD";
|
const std::string CURRENCY_CODE_AUD = "AUD";
|
||||||
const std::string CURRENCY_CODE_CAD = "CAD";
|
const std::string CURRENCY_CODE_CAD = "CAD";
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false);
|
std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char currency, bool useSuffixFormat = false, bool mowMode = false);
|
||||||
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
|
std::array<std::string, NUM_SCREENS> parseSatsPerCurrency(std::uint32_t price, char currencySymbol, bool withSatsSymbol);
|
||||||
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight);
|
||||||
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
||||||
|
|
|
@ -28,7 +28,12 @@ double getSupplyAtBlock(std::uint32_t blockNr)
|
||||||
return totalBitcoinInCirculation;
|
return totalBitcoinInCirculation;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
|
||||||
|
{
|
||||||
|
return formatNumberWithSuffix(num, numCharacters, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters, bool mowMode)
|
||||||
{
|
{
|
||||||
static char result[20]; // Adjust size as needed
|
static char result[20]; // Adjust size as needed
|
||||||
const long long quadrillion = 1000000000000000LL;
|
const long long quadrillion = 1000000000000000LL;
|
||||||
|
@ -56,30 +61,36 @@ std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters)
|
||||||
numDouble /= billion;
|
numDouble /= billion;
|
||||||
suffix = 'B';
|
suffix = 'B';
|
||||||
}
|
}
|
||||||
else if (num >= million || numDigits > 6)
|
else if (num >= million || numDigits > 6 || (mowMode && num >= thousand))
|
||||||
{
|
{
|
||||||
numDouble /= million;
|
numDouble /= million;
|
||||||
suffix = 'M';
|
suffix = 'M';
|
||||||
}
|
}
|
||||||
else if (num >= thousand || numDigits > 3)
|
else if (!mowMode && (num >= thousand || numDigits > 3))
|
||||||
{
|
{
|
||||||
numDouble /= thousand;
|
numDouble /= thousand;
|
||||||
suffix = 'K';
|
suffix = 'K';
|
||||||
}
|
}
|
||||||
else
|
else if (!mowMode)
|
||||||
{
|
{
|
||||||
snprintf(result, sizeof(result), "%llu", (unsigned long long)num);
|
snprintf(result, sizeof(result), "%llu", (unsigned long long)num);
|
||||||
// sprintf(result, "%llu", (unsigned long long)num);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
else // mowMode is true and num < 1000
|
||||||
|
{
|
||||||
|
numDouble /= million;
|
||||||
|
suffix = 'M';
|
||||||
|
}
|
||||||
|
|
||||||
// Add suffix
|
// Add suffix
|
||||||
int len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
|
int len = snprintf(result, sizeof(result), "%.0f%c", numDouble, suffix);
|
||||||
|
|
||||||
// If there's room, add decimal places
|
// If there's room, add more decimal places
|
||||||
if (len < numCharacters)
|
if (len < numCharacters)
|
||||||
{
|
{
|
||||||
snprintf(result, sizeof(result), "%.*f%c", numCharacters - len - 1, numDouble, suffix);
|
int restLen = mowMode ? numCharacters - len : numCharacters - len - 1;
|
||||||
|
|
||||||
|
snprintf(result, sizeof(result), "%.*f%c", restLen, numDouble, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -11,4 +11,5 @@ int modulo(int x,int N);
|
||||||
double getSupplyAtBlock(std::uint32_t blockNr);
|
double getSupplyAtBlock(std::uint32_t blockNr);
|
||||||
|
|
||||||
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters = 4);
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters = 4);
|
||||||
|
std::string formatNumberWithSuffix(std::uint64_t num, int numCharacters, bool mowMode);
|
||||||
int64_t getAmountInSatoshis(std::string bolt11);
|
int64_t getAmountInSatoshis(std::string bolt11);
|
|
@ -18,6 +18,8 @@
|
||||||
#define DEFAULT_DISABLE_FL false
|
#define DEFAULT_DISABLE_FL false
|
||||||
#define DEFAULT_OWN_DATA_SOURCE true
|
#define DEFAULT_OWN_DATA_SOURCE true
|
||||||
#define DEFAULT_STAGING_SOURCE false
|
#define DEFAULT_STAGING_SOURCE false
|
||||||
|
#define DEFAULT_MOW_MODE false
|
||||||
|
|
||||||
#define DEFAULT_V2_SOURCE_CURRENCY CURRENCY_USD
|
#define DEFAULT_V2_SOURCE_CURRENCY CURRENCY_USD
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -283,7 +283,10 @@ void prepareDisplayUpdateTask(void *pvParameters)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
|
if (epdContent[epdIndex].length() == 2) {
|
||||||
|
showChars(epdIndex, epdContent[epdIndex], updatePartial, &FONT_BIG);
|
||||||
|
}
|
||||||
|
else if (epdContent[epdIndex].length() > 1 && epdContent[epdIndex].indexOf(".") == -1)
|
||||||
{
|
{
|
||||||
if (epdContent[epdIndex].equals("STS"))
|
if (epdContent[epdIndex].equals("STS"))
|
||||||
{
|
{
|
||||||
|
@ -407,6 +410,32 @@ void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
displays[dispNum].print(bottom);
|
displays[dispNum].print(bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
|
// const GFXfont *font)
|
||||||
|
// {
|
||||||
|
// displays[dispNum].setRotation(2);
|
||||||
|
// displays[dispNum].setFont(font);
|
||||||
|
// displays[dispNum].setTextColor(getFgColor());
|
||||||
|
// int16_t tbx, tby;
|
||||||
|
// uint16_t tbw, tbh;
|
||||||
|
|
||||||
|
// displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
|
|
||||||
|
// // center the bounding box by transposition of the origin:
|
||||||
|
// uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
|
// uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
|
|
||||||
|
// displays[dispNum].fillScreen(getBgColor());
|
||||||
|
|
||||||
|
// displays[dispNum].setCursor(x, y);
|
||||||
|
// displays[dispNum].print(chars);
|
||||||
|
|
||||||
|
// // displays[dispNum].setCursor(10, 3);
|
||||||
|
// // displays[dispNum].setFont(&FONT_SMALL);
|
||||||
|
// // displays[dispNum].setTextColor(getFgColor());
|
||||||
|
// // displays[dispNum].println("Y = " + y);
|
||||||
|
// }
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial,
|
void showDigit(const uint dispNum, char chr, bool partial,
|
||||||
const GFXfont *font)
|
const GFXfont *font)
|
||||||
{
|
{
|
||||||
|
@ -466,6 +495,18 @@ void showDigit(const uint dispNum, char chr, bool partial,
|
||||||
// displays[dispNum].println("Y = " + y);
|
// displays[dispNum].println("Y = " + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t calculateDescent(const GFXfont *font) {
|
||||||
|
int16_t maxDescent = 0;
|
||||||
|
for (uint16_t i = font->first; i <= font->last; i++) {
|
||||||
|
GFXglyph *glyph = &font->glyph[i - font->first];
|
||||||
|
int16_t descent = glyph->yOffset;
|
||||||
|
if (descent > maxDescent) {
|
||||||
|
maxDescent = descent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxDescent;
|
||||||
|
}
|
||||||
|
|
||||||
void showChars(const uint dispNum, const String &chars, bool partial,
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
const GFXfont *font)
|
const GFXfont *font)
|
||||||
{
|
{
|
||||||
|
@ -475,12 +516,35 @@ void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
int16_t tbx, tby;
|
int16_t tbx, tby;
|
||||||
uint16_t tbw, tbh;
|
uint16_t tbw, tbh;
|
||||||
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
|
|
||||||
|
int16_t descent = calculateDescent(font);
|
||||||
|
|
||||||
// center the bounding box by transposition of the origin:
|
// center the bounding box by transposition of the origin:
|
||||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
displays[dispNum].setCursor(x, y);
|
// displays[dispNum].setCursor(x, y);
|
||||||
displays[dispNum].print(chars);
|
// displays[dispNum].print(chars);
|
||||||
|
|
||||||
|
for (int i = 0; i < chars.length(); i++) {
|
||||||
|
char c = chars[i];
|
||||||
|
if (c == '.' || c == ',') {
|
||||||
|
// For the dot, calculate its specific descent
|
||||||
|
GFXglyph *dotGlyph = &font->glyph[c -font->first];
|
||||||
|
int16_t dotDescent = dotGlyph->yOffset;
|
||||||
|
|
||||||
|
// Draw the dot with adjusted y-position
|
||||||
|
displays[dispNum].setCursor(x, y + dotDescent + dotGlyph->height);
|
||||||
|
displays[dispNum].print(c);
|
||||||
|
} else {
|
||||||
|
// For other characters, use the original y-position
|
||||||
|
displays[dispNum].setCursor(x, y);
|
||||||
|
displays[dispNum].print(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move x-position for the next character
|
||||||
|
x += font->glyph[c - font->first].xAdvance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBgColor() { return bgColor; }
|
int getBgColor() { return bgColor; }
|
||||||
|
|
|
@ -41,7 +41,7 @@ void workerTask(void *pvParameters) {
|
||||||
uint price = getPrice(currency);
|
uint price = getPrice(currency);
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
||||||
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE));
|
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE), preferences.getBool("mowMode", DEFAULT_MOW_MODE));
|
||||||
} else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) {
|
} else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) {
|
||||||
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -546,6 +546,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
"mdnsEnabled", "otaEnabled", "stealFocus",
|
"mdnsEnabled", "otaEnabled", "stealFocus",
|
||||||
"mcapBigChar", "useSatsSymbol", "useBlkCountdown",
|
"mcapBigChar", "useSatsSymbol", "useBlkCountdown",
|
||||||
"suffixPrice", "disableLeds", "ownDataSource",
|
"suffixPrice", "disableLeds", "ownDataSource",
|
||||||
|
"mowMode",
|
||||||
"flAlwaysOn", "flDisable", "flFlashOnUpd",
|
"flAlwaysOn", "flDisable", "flFlashOnUpd",
|
||||||
"mempoolSecure", "useNostr", "bitaxeEnabled",
|
"mempoolSecure", "useNostr", "bitaxeEnabled",
|
||||||
"nostrZapNotify", "stagingSource", "httpAuthEnabled"};
|
"nostrZapNotify", "stagingSource", "httpAuthEnabled"};
|
||||||
|
@ -687,6 +688,7 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root["useBlkCountdown"] = preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN);
|
root["useBlkCountdown"] = preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN);
|
||||||
root["suffixPrice"] = preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE);
|
root["suffixPrice"] = preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE);
|
||||||
root["disableLeds"] = preferences.getBool("disableLeds", DEFAULT_DISABLE_LEDS);
|
root["disableLeds"] = preferences.getBool("disableLeds", DEFAULT_DISABLE_LEDS);
|
||||||
|
root["mowMode"] = preferences.getBool("mowMode", DEFAULT_MOW_MODE);
|
||||||
|
|
||||||
root["hostnamePrefix"] = preferences.getString("hostnamePrefix", DEFAULT_HOSTNAME_PREFIX);
|
root["hostnamePrefix"] = preferences.getString("hostnamePrefix", DEFAULT_HOSTNAME_PREFIX);
|
||||||
root["hostname"] = getMyHostname();
|
root["hostname"] = getMyHostname();
|
||||||
|
|
|
@ -86,6 +86,33 @@ void test_PriceOf1MillionUsd(void)
|
||||||
TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS - 1].c_str());
|
TEST_ASSERT_EQUAL_STRING("M", output[NUM_SCREENS - 1].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_PriceSuffixMode(void)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parsePriceData(93000, '$', true, false);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("BTC/USD", output[0].c_str());
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_STRING("9", output[NUM_SCREENS - 5].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("3", output[NUM_SCREENS - 4].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING(".", output[NUM_SCREENS - 3].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("0", output[NUM_SCREENS - 2].c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING("K", output[NUM_SCREENS - 1].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_PriceSuffixModeMow(void)
|
||||||
|
{
|
||||||
|
std::array<std::string, NUM_SCREENS> output = parsePriceData(93000, '$', true, true);
|
||||||
|
|
||||||
|
std::string joined = joinArrayWithBrackets(output);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("$", output[0].c_str(), joined.c_str());
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE(".", output[NUM_SCREENS - 5].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("0", output[NUM_SCREENS - 4].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("9", output[NUM_SCREENS - 3].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("3", output[NUM_SCREENS - 2].c_str(), joined.c_str());
|
||||||
|
TEST_ASSERT_EQUAL_STRING_MESSAGE("M", output[NUM_SCREENS - 1].c_str(), joined.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
void test_McapLowerUsd(void)
|
void test_McapLowerUsd(void)
|
||||||
{
|
{
|
||||||
std::array<std::string, NUM_SCREENS> output = parseMarketCap(810000, 26000, '$', true);
|
std::array<std::string, NUM_SCREENS> output = parseMarketCap(810000, 26000, '$', true);
|
||||||
|
@ -203,6 +230,8 @@ int runUnityTests(void)
|
||||||
RUN_TEST(test_Mcap1TrillionEurSmallChars);
|
RUN_TEST(test_Mcap1TrillionEurSmallChars);
|
||||||
RUN_TEST(test_Mcap1TrillionJpy);
|
RUN_TEST(test_Mcap1TrillionJpy);
|
||||||
RUN_TEST(test_Mcap1TrillionJpySmallChars);
|
RUN_TEST(test_Mcap1TrillionJpySmallChars);
|
||||||
|
RUN_TEST(test_PriceSuffixMode);
|
||||||
|
RUN_TEST(test_PriceSuffixModeMow);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue