2023-11-07 00:11:12 +00:00
|
|
|
#include "screen_handler.hpp"
|
|
|
|
|
2023-11-12 11:38:28 +00:00
|
|
|
// TaskHandle_t priceUpdateTaskHandle;
|
|
|
|
// TaskHandle_t blockUpdateTaskHandle;
|
|
|
|
// TaskHandle_t timeUpdateTaskHandle;
|
2023-11-07 20:26:15 +00:00
|
|
|
TaskHandle_t taskScreenRotateTaskHandle;
|
2023-11-12 11:38:28 +00:00
|
|
|
TaskHandle_t workerTaskHandle;
|
2024-09-18 00:00:10 +00:00
|
|
|
|
2023-11-07 00:11:12 +00:00
|
|
|
|
2024-09-09 13:13:41 +00:00
|
|
|
std::array<std::string, NUM_SCREENS> taskEpdContent = {};
|
2023-11-07 00:11:12 +00:00
|
|
|
std::string priceString;
|
2023-11-13 11:27:34 +00:00
|
|
|
|
2023-11-12 11:38:28 +00:00
|
|
|
#define WORK_QUEUE_SIZE 10
|
2023-11-12 23:33:48 +00:00
|
|
|
QueueHandle_t workQueue = NULL;
|
2023-11-07 20:26:15 +00:00
|
|
|
|
2024-09-09 13:13:41 +00:00
|
|
|
uint currentScreen = SCREEN_BLOCK_HEIGHT;
|
2024-09-05 12:00:15 +00:00
|
|
|
uint currentCurrency = CURRENCY_USD;
|
2023-11-07 00:11:12 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void workerTask(void *pvParameters) {
|
|
|
|
WorkItem receivedItem;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
// Wait for a work item to be available in the queue
|
|
|
|
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) {
|
|
|
|
// Process the work item based on its type
|
|
|
|
switch (receivedItem.type) {
|
2024-07-29 18:49:46 +00:00
|
|
|
case TASK_BITAXE_UPDATE: {
|
|
|
|
if (getCurrentScreen() == SCREEN_BITAXE_HASHRATE) {
|
|
|
|
taskEpdContent =
|
|
|
|
parseBitaxeHashRate(getBitAxeHashRate());
|
|
|
|
} else if (getCurrentScreen() == SCREEN_BITAXE_BESTDIFF) {
|
|
|
|
taskEpdContent =
|
|
|
|
parseBitaxeBestDiff(getBitaxeBestDiff());
|
|
|
|
}
|
|
|
|
setEpdContent(taskEpdContent);
|
2024-12-18 02:17:21 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case TASK_MINING_POOL_STATS_UPDATE: {
|
|
|
|
if (getCurrentScreen() == SCREEN_MINING_POOL_STATS_HASHRATE) {
|
|
|
|
taskEpdContent =
|
|
|
|
parseMiningPoolStatsHashRate(preferences.getString("miningPoolName", DEFAULT_MINING_POOL_NAME).c_str(), getMiningPoolStatsHashRate());
|
2024-12-18 21:58:12 +00:00
|
|
|
} else if (getCurrentScreen() == SCREEN_MINING_POOL_STATS_EARNINGS) {
|
|
|
|
taskEpdContent =
|
|
|
|
parseMiningPoolStatsDailyEarnings(preferences.getString("miningPoolName", DEFAULT_MINING_POOL_NAME).c_str(), getMiningPoolStatsDailyEarnings());
|
2024-12-18 02:17:21 +00:00
|
|
|
}
|
|
|
|
setEpdContent(taskEpdContent);
|
|
|
|
break;
|
2024-07-29 18:49:46 +00:00
|
|
|
}
|
2023-11-30 21:56:50 +00:00
|
|
|
case TASK_PRICE_UPDATE: {
|
2024-09-05 12:00:15 +00:00
|
|
|
uint currency = getCurrentCurrency();
|
|
|
|
uint price = getPrice(currency);
|
2024-09-18 00:00:10 +00:00
|
|
|
|
2023-11-30 21:56:50 +00:00
|
|
|
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
2024-11-28 17:22:07 +00:00
|
|
|
taskEpdContent = parsePriceData(price, currency, preferences.getBool("suffixPrice", DEFAULT_SUFFIX_PRICE),
|
|
|
|
preferences.getBool("mowMode", DEFAULT_MOW_MODE),
|
|
|
|
preferences.getBool("suffixShareDot", DEFAULT_SUFFIX_SHARE_DOT)
|
|
|
|
);
|
2024-09-05 12:00:15 +00:00
|
|
|
} else if (getCurrentScreen() == SCREEN_SATS_PER_CURRENCY) {
|
|
|
|
taskEpdContent = parseSatsPerCurrency(price, currency, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
|
2023-11-30 21:56:50 +00:00
|
|
|
} else {
|
|
|
|
taskEpdContent =
|
2024-09-05 12:00:15 +00:00
|
|
|
parseMarketCap(getBlockHeight(), price, currency,
|
2024-07-11 12:08:37 +00:00
|
|
|
preferences.getBool("mcapBigChar", DEFAULT_MCAP_BIG_CHAR));
|
2023-11-30 21:56:50 +00:00
|
|
|
}
|
2023-11-08 11:18:59 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
setEpdContent(taskEpdContent);
|
2023-11-30 21:56:50 +00:00
|
|
|
break;
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
2024-03-10 19:24:55 +00:00
|
|
|
case TASK_FEE_UPDATE: {
|
|
|
|
if (getCurrentScreen() == SCREEN_BLOCK_FEE_RATE) {
|
|
|
|
taskEpdContent = parseBlockFees(static_cast<std::uint16_t>(getBlockMedianFee()));
|
|
|
|
setEpdContent(taskEpdContent);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-11-30 21:56:50 +00:00
|
|
|
case TASK_BLOCK_UPDATE: {
|
|
|
|
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
|
|
|
taskEpdContent = parseBlockHeight(getBlockHeight());
|
|
|
|
} else {
|
2024-07-11 12:08:37 +00:00
|
|
|
taskEpdContent = parseHalvingCountdown(getBlockHeight(), preferences.getBool("useBlkCountdown", DEFAULT_USE_BLOCK_COUNTDOWN));
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:56:50 +00:00
|
|
|
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
|
|
|
getCurrentScreen() == SCREEN_BLOCK_HEIGHT) {
|
|
|
|
setEpdContent(taskEpdContent);
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
2023-11-30 21:56:50 +00:00
|
|
|
break;
|
2023-11-08 11:18:59 +00:00
|
|
|
}
|
2023-11-30 21:56:50 +00:00
|
|
|
case TASK_TIME_UPDATE: {
|
|
|
|
if (getCurrentScreen() == SCREEN_TIME) {
|
|
|
|
time_t currentTime;
|
|
|
|
struct tm timeinfo;
|
|
|
|
time(¤tTime);
|
|
|
|
localtime_r(¤tTime, &timeinfo);
|
|
|
|
std::string timeString;
|
|
|
|
|
|
|
|
String minute = String(timeinfo.tm_min);
|
|
|
|
if (minute.length() < 2) {
|
|
|
|
minute = "0" + minute;
|
|
|
|
}
|
|
|
|
|
|
|
|
timeString =
|
|
|
|
std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
|
|
|
timeString.insert(timeString.begin(),
|
|
|
|
NUM_SCREENS - timeString.length(), ' ');
|
|
|
|
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" +
|
|
|
|
std::to_string(timeinfo.tm_mon + 1);
|
|
|
|
|
|
|
|
for (uint i = 1; i < NUM_SCREENS; i++) {
|
|
|
|
taskEpdContent[i] = timeString[i];
|
|
|
|
}
|
|
|
|
setEpdContent(taskEpdContent);
|
|
|
|
}
|
2023-11-08 11:18:59 +00:00
|
|
|
|
2023-11-30 21:56:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Add more cases for additional task types
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
2023-11-07 20:26:15 +00:00
|
|
|
}
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
2023-11-07 20:26:15 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void taskScreenRotate(void *pvParameters) {
|
|
|
|
for (;;) {
|
|
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
|
|
|
2024-07-29 18:49:46 +00:00
|
|
|
nextScreen();
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
2023-11-07 20:26:15 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void setupTasks() {
|
|
|
|
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
2023-11-12 11:38:28 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY,
|
|
|
|
&workerTaskHandle);
|
2023-11-12 11:38:28 +00:00
|
|
|
|
2024-09-05 12:00:15 +00:00
|
|
|
xTaskCreate(taskScreenRotate, "rotateScreen", 4096, NULL, tskIDLE_PRIORITY,
|
2023-11-30 21:38:01 +00:00
|
|
|
&taskScreenRotateTaskHandle);
|
2023-11-08 14:27:22 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
waitUntilNoneBusy();
|
2024-09-09 13:13:41 +00:00
|
|
|
|
|
|
|
if (findScreenIndexByValue(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN)) != -1)
|
|
|
|
setCurrentScreen(preferences.getUInt("currentScreen", DEFAULT_CURRENT_SCREEN));
|
2023-11-07 20:26:15 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
uint getCurrentScreen() { return currentScreen; }
|
2023-11-07 20:26:15 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void setCurrentScreen(uint newScreen) {
|
|
|
|
if (newScreen != SCREEN_CUSTOM) {
|
|
|
|
preferences.putUInt("currentScreen", newScreen);
|
|
|
|
}
|
2023-11-07 20:26:15 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
currentScreen = newScreen;
|
2023-11-08 19:29:06 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
switch (currentScreen) {
|
2023-11-30 21:56:50 +00:00
|
|
|
case SCREEN_TIME: {
|
|
|
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
|
|
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SCREEN_HALVING_COUNTDOWN:
|
|
|
|
case SCREEN_BLOCK_HEIGHT: {
|
|
|
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
|
|
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SCREEN_MARKET_CAP:
|
2024-09-05 12:00:15 +00:00
|
|
|
case SCREEN_SATS_PER_CURRENCY:
|
2023-11-30 21:56:50 +00:00
|
|
|
case SCREEN_BTC_TICKER: {
|
|
|
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
|
|
|
// xTaskNotifyGive(priceUpdateTaskHandle);
|
|
|
|
break;
|
|
|
|
}
|
2024-03-10 19:37:45 +00:00
|
|
|
case SCREEN_BLOCK_FEE_RATE: {
|
|
|
|
WorkItem blockUpdate = {TASK_FEE_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
|
|
|
break;
|
|
|
|
}
|
2024-07-29 18:49:46 +00:00
|
|
|
case SCREEN_BITAXE_BESTDIFF:
|
|
|
|
case SCREEN_BITAXE_HASHRATE: {
|
|
|
|
if (preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED)) {
|
|
|
|
WorkItem bitaxeUpdate = {TASK_BITAXE_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &bitaxeUpdate, portMAX_DELAY);
|
|
|
|
} else {
|
|
|
|
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2024-12-18 02:17:21 +00:00
|
|
|
}
|
2024-12-18 21:58:12 +00:00
|
|
|
case SCREEN_MINING_POOL_STATS_HASHRATE:
|
|
|
|
case SCREEN_MINING_POOL_STATS_EARNINGS: {
|
2024-12-18 23:07:44 +00:00
|
|
|
if (preferences.getBool("miningPoolStats", DEFAULT_MINING_POOL_STATS_ENABLED)) {
|
2024-12-18 02:17:21 +00:00
|
|
|
WorkItem miningPoolStatsUpdate = {TASK_MINING_POOL_STATS_UPDATE, 0};
|
|
|
|
xQueueSend(workQueue, &miningPoolStatsUpdate, portMAX_DELAY);
|
|
|
|
} else {
|
|
|
|
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2024-07-29 18:49:46 +00:00
|
|
|
}
|
2023-11-30 21:38:01 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:56:50 +00:00
|
|
|
if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle);
|
2023-11-08 11:18:59 +00:00
|
|
|
}
|
|
|
|
|
2024-09-05 12:00:15 +00:00
|
|
|
bool isCurrencySpecific(uint screen) {
|
|
|
|
switch (screen) {
|
|
|
|
case SCREEN_BTC_TICKER:
|
|
|
|
case SCREEN_SATS_PER_CURRENCY:
|
|
|
|
case SCREEN_MARKET_CAP:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void nextScreen() {
|
2024-07-29 18:49:46 +00:00
|
|
|
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
|
|
|
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
|
|
|
|
2024-09-05 12:00:15 +00:00
|
|
|
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE) && isCurrencySpecific(getCurrentScreen())) {
|
|
|
|
std::vector<std::string> ac = getActiveCurrencies();
|
|
|
|
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
|
|
|
if (getCurrencyCode(getCurrentCurrency()) != ac.back()) {
|
|
|
|
auto it = std::find(ac.begin(), ac.end(), curCode);
|
|
|
|
if (it != ac.end()) {
|
|
|
|
size_t index = std::distance(ac.begin(), it);
|
|
|
|
setCurrentCurrency(getCurrencyChar(ac.at(index+1)));
|
|
|
|
setCurrentScreen(getCurrentScreen());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setCurrentCurrency(getCurrencyChar(ac.front()));
|
|
|
|
}
|
|
|
|
|
2024-07-29 18:49:46 +00:00
|
|
|
int newCurrentScreen;
|
|
|
|
|
|
|
|
if (currentIndex < screenMappings.size() - 1) {
|
|
|
|
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
|
|
|
} else {
|
|
|
|
newCurrentScreen = screenMappings.front().value;
|
|
|
|
}
|
|
|
|
|
2024-09-02 20:44:23 +00:00
|
|
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
2023-11-08 11:18:59 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
while (!preferences.getBool(key.c_str(), true)) {
|
2024-07-29 18:49:46 +00:00
|
|
|
currentIndex = findScreenIndexByValue(newCurrentScreen);
|
|
|
|
if (currentIndex < screenMappings.size() - 1) {
|
|
|
|
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
|
|
|
} else {
|
|
|
|
newCurrentScreen = screenMappings.front().value;
|
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
|
|
|
}
|
2024-09-02 20:44:23 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
setCurrentScreen(newCurrentScreen);
|
2023-11-08 11:18:59 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void previousScreen() {
|
2024-07-29 18:49:46 +00:00
|
|
|
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
|
|
|
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
|
|
|
|
2024-09-05 12:00:15 +00:00
|
|
|
if (preferences.getBool("ownDataSource", DEFAULT_OWN_DATA_SOURCE) && isCurrencySpecific(getCurrentScreen())) {
|
|
|
|
std::vector<std::string> ac = getActiveCurrencies();
|
|
|
|
std::string curCode = getCurrencyCode(getCurrentCurrency());
|
|
|
|
if (getCurrencyCode(getCurrentCurrency()) != ac.front()) {
|
|
|
|
auto it = std::find(ac.begin(), ac.end(), curCode);
|
|
|
|
if (it != ac.end()) {
|
|
|
|
size_t index = std::distance(ac.begin(), it);
|
|
|
|
setCurrentCurrency(getCurrencyChar(ac.at(index-1)));
|
|
|
|
setCurrentScreen(getCurrentScreen());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setCurrentCurrency(getCurrencyChar(ac.back()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-07-29 18:49:46 +00:00
|
|
|
int newCurrentScreen;
|
|
|
|
|
|
|
|
if (currentIndex > 0) {
|
|
|
|
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
|
|
|
} else {
|
|
|
|
newCurrentScreen = screenMappings.back().value;
|
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
2023-11-08 11:18:59 +00:00
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
while (!preferences.getBool(key.c_str(), true)) {
|
2024-07-29 18:49:46 +00:00
|
|
|
int currentIndex = findScreenIndexByValue(newCurrentScreen);
|
|
|
|
if (currentIndex > 0) {
|
|
|
|
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
|
|
|
} else {
|
|
|
|
newCurrentScreen = screenMappings.back().value;
|
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
|
|
|
}
|
|
|
|
setCurrentScreen(newCurrentScreen);
|
2023-11-08 11:18:59 +00:00
|
|
|
}
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
void showSystemStatusScreen() {
|
2024-09-02 20:44:23 +00:00
|
|
|
std::array<String, NUM_SCREENS> sysStatusEpdContent;
|
|
|
|
std::fill(sysStatusEpdContent.begin(), sysStatusEpdContent.end(), "");
|
|
|
|
|
2023-11-30 21:38:01 +00:00
|
|
|
|
|
|
|
String ipAddr = WiFi.localIP().toString();
|
|
|
|
String subNet = WiFi.subnetMask().toString();
|
|
|
|
|
|
|
|
sysStatusEpdContent[0] = "IP/Subnet";
|
|
|
|
|
|
|
|
int ipAddrPos = 0;
|
|
|
|
int subnetPos = 0;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) +
|
|
|
|
"/" + subNet.substring(0, subNet.indexOf('.'));
|
|
|
|
ipAddrPos = ipAddr.indexOf('.') + 1;
|
|
|
|
subnetPos = subNet.indexOf('.') + 1;
|
|
|
|
ipAddr = ipAddr.substring(ipAddrPos);
|
|
|
|
subNet = subNet.substring(subnetPos);
|
|
|
|
}
|
|
|
|
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
|
|
|
|
|
|
|
sysStatusEpdContent[NUM_SCREENS - 1] =
|
|
|
|
String((int)round(ESP.getFreeHeap() / 1024)) + "/" +
|
|
|
|
(int)round(ESP.getHeapSize() / 1024);
|
|
|
|
setCurrentScreen(SCREEN_CUSTOM);
|
|
|
|
setEpdContent(sysStatusEpdContent);
|
2024-09-05 12:00:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void setCurrentCurrency(char currency) {
|
|
|
|
currentCurrency = currency;
|
|
|
|
preferences.putUChar("lastCurrency", currency);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint getCurrentCurrency() {
|
|
|
|
return currentCurrency;
|
2023-11-07 00:11:12 +00:00
|
|
|
}
|