Added BitAxe support
This commit is contained in:
parent
ca1c7178f1
commit
b13c7242a6
18 changed files with 837 additions and 46 deletions
61
src/lib/bitaxe_fetch.cpp
Normal file
61
src/lib/bitaxe_fetch.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "bitaxe_fetch.hpp"
|
||||
|
||||
TaskHandle_t bitaxeFetchTaskHandle;
|
||||
|
||||
std::string bitaxeHashrate;
|
||||
std::string bitaxeBestDiff;
|
||||
|
||||
std::string getBitAxeHashRate()
|
||||
{
|
||||
return bitaxeHashrate;
|
||||
}
|
||||
|
||||
std::string getBitaxeBestDiff()
|
||||
{
|
||||
return bitaxeBestDiff;
|
||||
}
|
||||
|
||||
void taskBitaxeFetch(void *pvParameters)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
HTTPClient http;
|
||||
http.setUserAgent(USER_AGENT);
|
||||
String bitaxeApiUrl = "http://" + preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME) + "/api/system/info";
|
||||
http.begin(bitaxeApiUrl.c_str());
|
||||
|
||||
int httpCode = http.GET();
|
||||
|
||||
if (httpCode == 200)
|
||||
{
|
||||
String payload = http.getString();
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, payload);
|
||||
bitaxeHashrate = std::to_string(static_cast<int>(std::round(doc["hashRate"].as<float>())));
|
||||
bitaxeBestDiff = doc["bestDiff"].as<std::string>();
|
||||
|
||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BITAXE_HASHRATE || getCurrentScreen() == SCREEN_BITAXE_BESTDIFF))
|
||||
{
|
||||
WorkItem priceUpdate = {TASK_BITAXE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(
|
||||
F("Error retrieving BitAxe data. HTTP status code: "));
|
||||
Serial.println(httpCode);
|
||||
Serial.println(bitaxeApiUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setupBitaxeFetchTask()
|
||||
{
|
||||
xTaskCreate(taskBitaxeFetch, "bitaxeFetch", (6 * 1024), NULL, tskIDLE_PRIORITY,
|
||||
&bitaxeFetchTaskHandle);
|
||||
|
||||
xTaskNotifyGive(bitaxeFetchTaskHandle);
|
||||
}
|
15
src/lib/bitaxe_fetch.hpp
Normal file
15
src/lib/bitaxe_fetch.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#include "lib/config.hpp"
|
||||
#include "lib/shared.hpp"
|
||||
|
||||
extern TaskHandle_t bitaxeFetchTaskHandle;
|
||||
|
||||
void setupBitaxeFetchTask();
|
||||
void taskBitaxeFetch(void *pvParameters);
|
||||
|
||||
std::string getBitAxeHashRate();
|
||||
std::string getBitaxeBestDiff();
|
|
@ -14,10 +14,14 @@ BH1750 bh1750;
|
|||
bool hasLuxSensor = false;
|
||||
#endif
|
||||
|
||||
std::vector<std::string> screenNameMap(SCREEN_COUNT);
|
||||
std::vector<ScreenMapping> screenMappings;
|
||||
std::mutex mcpMutex;
|
||||
uint lastTimeSync;
|
||||
|
||||
void addScreenMapping(int value, const char* name) {
|
||||
screenMappings.push_back({value, name});
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
setupPreferences();
|
||||
|
@ -250,6 +254,7 @@ void syncTime()
|
|||
lastTimeSync = esp_timer_get_time() / 1000000;
|
||||
}
|
||||
|
||||
|
||||
void setupPreferences()
|
||||
{
|
||||
preferences.begin("btclock", false);
|
||||
|
@ -259,13 +264,26 @@ void setupPreferences()
|
|||
setBlockHeight(preferences.getUInt("blockHeight", INITIAL_BLOCK_HEIGHT));
|
||||
setPrice(preferences.getUInt("lastPrice", INITIAL_LAST_PRICE));
|
||||
|
||||
screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
|
||||
screenNameMap[SCREEN_BLOCK_FEE_RATE] = "Block Fee Rate";
|
||||
screenNameMap[SCREEN_MSCW_TIME] = "Sats per dollar";
|
||||
screenNameMap[SCREEN_BTC_TICKER] = "Ticker";
|
||||
screenNameMap[SCREEN_TIME] = "Time";
|
||||
screenNameMap[SCREEN_HALVING_COUNTDOWN] = "Halving countdown";
|
||||
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
||||
addScreenMapping(SCREEN_BLOCK_HEIGHT, "Block Height");
|
||||
addScreenMapping(SCREEN_MSCW_TIME, "Sats per dollar");
|
||||
addScreenMapping(SCREEN_BTC_TICKER, "Ticker");
|
||||
addScreenMapping(SCREEN_TIME, "Time");
|
||||
addScreenMapping(SCREEN_HALVING_COUNTDOWN, "Halving countdown");
|
||||
addScreenMapping(SCREEN_MARKET_CAP, "Market Cap");
|
||||
addScreenMapping(SCREEN_BLOCK_FEE_RATE, "Block Fee Rate");
|
||||
|
||||
// screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
|
||||
// screenNameMap[SCREEN_BLOCK_FEE_RATE] = "Block Fee Rate";
|
||||
// screenNameMap[SCREEN_MSCW_TIME] = "Sats per dollar";
|
||||
// screenNameMap[SCREEN_BTC_TICKER] = "Ticker";
|
||||
// screenNameMap[SCREEN_TIME] = "Time";
|
||||
// screenNameMap[SCREEN_HALVING_COUNTDOWN] = "Halving countdown";
|
||||
// screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
||||
|
||||
if (preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED)) {
|
||||
addScreenMapping(SCREEN_BITAXE_HASHRATE, "BitAxe Hashrate");
|
||||
addScreenMapping(SCREEN_BITAXE_BESTDIFF, "BitAxe Best Difficulty");
|
||||
}
|
||||
}
|
||||
|
||||
void setupWebsocketClients(void *pvParameters)
|
||||
|
@ -281,6 +299,11 @@ void setupWebsocketClients(void *pvParameters)
|
|||
setupPriceNotify();
|
||||
}
|
||||
|
||||
if (preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED))
|
||||
{
|
||||
setupBitaxeFetchTask();
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
@ -304,7 +327,7 @@ void finishSetup()
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> getScreenNameMap() { return screenNameMap; }
|
||||
std::vector<ScreenMapping> getScreenNameMap() { return screenMappings; }
|
||||
|
||||
void setupMcp()
|
||||
{
|
||||
|
@ -419,6 +442,9 @@ void setupHardware()
|
|||
Serial.println(F("Found BH1750"));
|
||||
hasLuxSensor = true;
|
||||
bh1750.begin(BH1750::CONTINUOUS_LOW_RES_MODE, 0x5C);
|
||||
} else {
|
||||
Serial.println(F("BH1750 Not found"));
|
||||
hasLuxSensor = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -796,3 +822,12 @@ String getFsRev()
|
|||
fsHash.close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int findScreenIndexByValue(int value) {
|
||||
for (int i = 0; i < screenMappings.size(); i++) {
|
||||
if (screenMappings[i].value == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // Return -1 if value is not found
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "lib/led_handler.hpp"
|
||||
#include "lib/ota.hpp"
|
||||
#include "lib/nostr_notify.hpp"
|
||||
#include "lib/bitaxe_fetch.hpp"
|
||||
|
||||
#include "lib/price_notify.hpp"
|
||||
#include "lib/screen_handler.hpp"
|
||||
|
@ -53,7 +54,7 @@ extern PCA9685 flArray;
|
|||
#endif
|
||||
|
||||
String getMyHostname();
|
||||
std::vector<std::string> getScreenNameMap();
|
||||
std::vector<ScreenMapping> getScreenNameMap();
|
||||
|
||||
std::vector<std::string> getLocalUrl();
|
||||
bool improv_connectWifi(std::string ssid, std::string password);
|
||||
|
@ -67,4 +68,7 @@ void improv_set_error(improv::Error error);
|
|||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
String getHwRev();
|
||||
bool isWhiteVersion();
|
||||
String getFsRev();
|
||||
String getFsRev();
|
||||
|
||||
void addScreenMapping(int value, const char* name);
|
||||
int findScreenIndexByValue(int value);
|
|
@ -45,3 +45,7 @@
|
|||
#define DEFAULT_TIMER_ACTIVE true
|
||||
#define DEFAULT_TIMER_SECONDS 1800
|
||||
#define DEFAULT_CURRENT_SCREEN 0
|
||||
|
||||
#define DEFAULT_BITAXE_ENABLED false
|
||||
#define DEFAULT_BITAXE_HOSTNAME "bitaxe1"
|
||||
|
||||
|
|
|
@ -264,6 +264,10 @@ void prepareDisplayUpdateTask(void *pvParameters)
|
|||
{
|
||||
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
||||
}
|
||||
else if (epdContent[epdIndex].startsWith(F("mdi")))
|
||||
{
|
||||
renderIcon(epdIndex, epdContent[epdIndex], updatePartial);
|
||||
}
|
||||
else if (epdContent[epdIndex].length() > 5)
|
||||
{
|
||||
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
||||
|
@ -513,6 +517,24 @@ void renderText(const uint dispNum, const String &text, bool partial)
|
|||
}
|
||||
}
|
||||
|
||||
void renderIcon(const uint dispNum, const String &text, bool partial)
|
||||
{
|
||||
displays[dispNum].setRotation(2);
|
||||
|
||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||
displays[dispNum].height());
|
||||
displays[dispNum].fillScreen(getBgColor());
|
||||
displays[dispNum].setTextColor(getFgColor());
|
||||
|
||||
uint iconIndex = 0;
|
||||
if (text.endsWith("rocket")) {
|
||||
iconIndex = 1;
|
||||
}
|
||||
|
||||
displays[dispNum].drawInvertedBitmap(0,0, epd_icons_allArray[iconIndex], 122, 250, getFgColor());
|
||||
|
||||
}
|
||||
|
||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
||||
{
|
||||
#ifdef USE_QR
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "fonts/fonts.hpp"
|
||||
#include "lib/config.hpp"
|
||||
#include "lib/shared.hpp"
|
||||
#include "icons/icons.h"
|
||||
|
||||
#ifdef USE_QR
|
||||
#include "qrcodegen.h"
|
||||
|
@ -42,6 +43,7 @@ int getFgColor();
|
|||
void setBgColor(int color);
|
||||
void setFgColor(int color);
|
||||
|
||||
void renderIcon(const uint dispNum, const String &text, bool partial);
|
||||
void renderText(const uint dispNum, const String &text, bool partial);
|
||||
void renderQr(const uint dispNum, const String &text, bool partial);
|
||||
|
||||
|
|
|
@ -27,6 +27,18 @@ void workerTask(void *pvParameters) {
|
|||
|
||||
// Process the work item based on its type
|
||||
switch (receivedItem.type) {
|
||||
case TASK_BITAXE_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_BITAXE_HASHRATE) {
|
||||
taskEpdContent =
|
||||
parseBitaxeHashRate(getBitAxeHashRate());
|
||||
} else if (getCurrentScreen() == SCREEN_BITAXE_BESTDIFF) {
|
||||
taskEpdContent =
|
||||
parseBitaxeBestDiff(getBitaxeBestDiff());
|
||||
}
|
||||
setEpdContent(taskEpdContent);
|
||||
|
||||
}
|
||||
break;
|
||||
case TASK_PRICE_UPDATE: {
|
||||
uint price = getPrice();
|
||||
char priceSymbol = '$';
|
||||
|
@ -104,15 +116,7 @@ void taskScreenRotate(void *pvParameters) {
|
|||
for (;;) {
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
|
||||
int nextScreen = (currentScreen + 1) % SCREEN_COUNT;
|
||||
String key = "screen" + String(nextScreen) + "Visible";
|
||||
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
nextScreen = (nextScreen + 1) % SCREEN_COUNT;
|
||||
key = "screen" + String(nextScreen) + "Visible";
|
||||
}
|
||||
|
||||
setCurrentScreen(nextScreen);
|
||||
nextScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +128,11 @@ void IRAM_ATTR minuteTimerISR(void *arg) {
|
|||
if (priceFetchTaskHandle != NULL) {
|
||||
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
if (bitaxeFetchTaskHandle != NULL) {
|
||||
vTaskNotifyGiveFromISR(bitaxeFetchTaskHandle, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
@ -245,28 +254,72 @@ void setCurrentScreen(uint newScreen) {
|
|||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventSourceTaskHandle != NULL) xTaskNotifyGive(eventSourceTaskHandle);
|
||||
}
|
||||
|
||||
void nextScreen() {
|
||||
int newCurrentScreen = (getCurrentScreen() + 1) % SCREEN_COUNT;
|
||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
||||
|
||||
int newCurrentScreen;
|
||||
|
||||
if (currentIndex < screenMappings.size() - 1) {
|
||||
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.front().value;
|
||||
}
|
||||
|
||||
String key = "screen" + String(screenMappings[currentIndex - 1].value) + "Visible";
|
||||
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
newCurrentScreen = (newCurrentScreen + 1) % SCREEN_COUNT;
|
||||
currentIndex = findScreenIndexByValue(newCurrentScreen);
|
||||
if (currentIndex < screenMappings.size() - 1) {
|
||||
newCurrentScreen = (screenMappings[currentIndex + 1].value);
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.front().value;
|
||||
}
|
||||
|
||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
}
|
||||
|
||||
setCurrentScreen(newCurrentScreen);
|
||||
}
|
||||
|
||||
void previousScreen() {
|
||||
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
||||
int currentIndex = findScreenIndexByValue(getCurrentScreen());
|
||||
std::vector<ScreenMapping> screenMappings = getScreenNameMap();
|
||||
|
||||
int newCurrentScreen;
|
||||
|
||||
if (currentIndex > 0) {
|
||||
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.back().value;
|
||||
}
|
||||
|
||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
|
||||
while (!preferences.getBool(key.c_str(), true)) {
|
||||
newCurrentScreen = modulo(newCurrentScreen - 1, SCREEN_COUNT);
|
||||
int currentIndex = findScreenIndexByValue(newCurrentScreen);
|
||||
if (currentIndex > 0) {
|
||||
newCurrentScreen = screenMappings[currentIndex - 1].value;
|
||||
} else {
|
||||
newCurrentScreen = screenMappings.back().value;
|
||||
}
|
||||
|
||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||
}
|
||||
setCurrentScreen(newCurrentScreen);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <freertos/task.h>
|
||||
|
||||
#include <data_handler.hpp>
|
||||
#include <bitaxe_handler.hpp>
|
||||
|
||||
#include "lib/epd.hpp"
|
||||
#include "lib/price_fetch.hpp"
|
||||
|
@ -25,7 +26,8 @@ typedef enum {
|
|||
TASK_PRICE_UPDATE,
|
||||
TASK_BLOCK_UPDATE,
|
||||
TASK_FEE_UPDATE,
|
||||
TASK_TIME_UPDATE
|
||||
TASK_TIME_UPDATE,
|
||||
TASK_BITAXE_UPDATE
|
||||
} TaskType;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -35,6 +35,8 @@ const PROGMEM int SCREEN_TIME = 3;
|
|||
const PROGMEM int SCREEN_HALVING_COUNTDOWN = 4;
|
||||
const PROGMEM int SCREEN_MARKET_CAP = 5;
|
||||
const PROGMEM int SCREEN_BLOCK_FEE_RATE = 6;
|
||||
const PROGMEM int SCREEN_BITAXE_HASHRATE = 80;
|
||||
const PROGMEM int SCREEN_BITAXE_BESTDIFF = 81;
|
||||
|
||||
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
||||
const PROGMEM int SCREEN_CUSTOM = 99;
|
||||
|
@ -58,4 +60,9 @@ struct SpiRamAllocator : ArduinoJson::Allocator {
|
|||
void* reallocate(void* ptr, size_t new_size) override {
|
||||
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
};
|
||||
|
||||
struct ScreenMapping {
|
||||
int value;
|
||||
const char* name;
|
||||
};
|
|
@ -443,7 +443,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
|||
settings["timePerScreen"].as<uint>() * 60);
|
||||
}
|
||||
|
||||
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay"};
|
||||
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname"};
|
||||
|
||||
for (String setting : strSettings)
|
||||
{
|
||||
|
@ -478,7 +478,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
|||
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd",
|
||||
"mdnsEnabled", "otaEnabled", "stealFocus",
|
||||
"mcapBigChar", "useSatsSymbol", "useBlkCountdown",
|
||||
"suffixPrice", "disableLeds", "ownDataSource", "flAlwaysOn", "flFlashOnUpd", "mempoolSecure", "useNostr"};
|
||||
"suffixPrice", "disableLeds", "ownDataSource", "flAlwaysOn", "flFlashOnUpd", "mempoolSecure", "useNostr", "bitaxeEnabled"};
|
||||
|
||||
for (String setting : boolSettings)
|
||||
{
|
||||
|
@ -601,6 +601,9 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
root["nostrPubKey"] = preferences.getString("nostrPubKey", DEFAULT_NOSTR_NPUB);
|
||||
root["nostrRelay"] = preferences.getString("nostrRelay", DEFAULT_NOSTR_RELAY);
|
||||
|
||||
root["bitaxeEnabled"] = preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED);
|
||||
root["bitaxeHostname"] = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME);
|
||||
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
root["hasFrontlight"] = true;
|
||||
root["flMaxBrightness"] = preferences.getUInt("flMaxBrightness", DEFAULT_FL_MAX_BRIGHTNESS);
|
||||
|
@ -629,14 +632,14 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
#endif
|
||||
JsonArray screens = root["screens"].to<JsonArray>();
|
||||
|
||||
std::vector<std::string> screenNameMap = getScreenNameMap();
|
||||
std::vector<ScreenMapping> screenNameMap = getScreenNameMap();
|
||||
|
||||
for (int i = 0; i < screenNameMap.size(); i++)
|
||||
{
|
||||
JsonObject o = screens.add<JsonObject>();
|
||||
String key = "screen" + String(i) + "Visible";
|
||||
o["id"] = i;
|
||||
o["name"] = screenNameMap[i];
|
||||
String key = "screen" + String(screenNameMap.at(i).value) + "Visible";
|
||||
o["id"] = screenNameMap.at(i).value;
|
||||
o["name"] = screenNameMap.at(i).name;
|
||||
o["enabled"] = preferences.getBool(key.c_str(), true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue