Upgrade ArduinoJson to version 7, add Block Fee Rate screen
This commit is contained in:
parent
c49b8edcb8
commit
2ca85ff479
17 changed files with 128 additions and 43 deletions
|
@ -1,11 +1,11 @@
|
|||
dependencies:
|
||||
esp_littlefs:
|
||||
component_hash: 66d5afe7ad323d0159d04e296c14ffa0e39156502bc15e0520eff2af392d3aa4
|
||||
component_hash: 6ae78edac4f81c605d6d7bff75f4f9a45d25938e4796347f91ea975ed3123326
|
||||
source:
|
||||
git: https://github.com/joltwallet/esp_littlefs.git
|
||||
path: .
|
||||
type: git
|
||||
version: 41873c20fb5cdbcf28d7d6cc04e4bcb4a1305317
|
||||
version: fd64733cdf248c7a7eb207db7d28124f8857fe0b
|
||||
idf:
|
||||
component_hash: null
|
||||
source:
|
||||
|
|
|
@ -87,6 +87,28 @@ std::array<std::string, NUM_SCREENS> parseBlockHeight(std::uint32_t blockHeight)
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::array<std::string, NUM_SCREENS> parseBlockFees(std::uint16_t blockFees) {
|
||||
std::array<std::string, NUM_SCREENS> ret;
|
||||
std::string blockFeesString = std::to_string(blockFees);
|
||||
std::uint32_t firstIndex = 0;
|
||||
|
||||
if (blockFeesString.length() < NUM_SCREENS)
|
||||
{
|
||||
blockFeesString.insert(blockFeesString.begin(), NUM_SCREENS - blockFeesString.length() - 1, ' ');
|
||||
ret[0] = "FEE/RATE";
|
||||
firstIndex = 1;
|
||||
}
|
||||
|
||||
for (uint i = firstIndex; i < NUM_SCREENS-1; i++)
|
||||
{
|
||||
ret[i] = blockFeesString[i];
|
||||
}
|
||||
|
||||
ret[NUM_SCREENS-1] = "sat/vB";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::array<std::string, NUM_SCREENS> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks)
|
||||
{
|
||||
std::array<std::string, NUM_SCREENS> ret;
|
||||
|
|
|
@ -9,4 +9,5 @@ std::array<std::string, NUM_SCREENS> parsePriceData(std::uint32_t price, char cu
|
|||
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> parseHalvingCountdown(std::uint32_t blockHeight, bool asBlocks);
|
||||
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
||||
std::array<std::string, NUM_SCREENS> parseMarketCap(std::uint32_t blockHeight, std::uint32_t price, char currencySymbol, bool bigChars);
|
||||
std::array<std::string, NUM_SCREENS> parseBlockFees(std::uint16_t blockFees);
|
||||
|
|
|
@ -30,9 +30,9 @@ build_unflags =
|
|||
-Werror=all
|
||||
-fno-exceptions
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson@^6.21.5
|
||||
bblanchon/ArduinoJson@^7.0.3
|
||||
esphome/Improv@^1.2.3
|
||||
esphome/ESPAsyncWebServer-esphome@^3.1.0
|
||||
mathieucarbou/ESP Async WebServer
|
||||
adafruit/Adafruit BusIO@^1.15.0
|
||||
adafruit/Adafruit MCP23017 Arduino Library@^2.3.2
|
||||
adafruit/Adafruit NeoPixel@^1.12.0
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
char *wsServer;
|
||||
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
||||
uint currentBlockHeight = 816000;
|
||||
uint blockMedianFee = 1;
|
||||
bool blockNotifyInit = false;
|
||||
|
||||
// const char *mempoolWsCert = R"(-----BEGIN CERTIFICATE-----
|
||||
|
@ -103,7 +104,7 @@ void setupBlockNotify() {
|
|||
void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
||||
int32_t event_id, void *event_data) {
|
||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\"]}";
|
||||
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\", \"mempool-blocks\"]}";
|
||||
switch (event_id) {
|
||||
case WEBSOCKET_EVENT_CONNECTED:
|
||||
blockNotifyInit = true;
|
||||
|
@ -130,16 +131,27 @@ void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
|||
}
|
||||
|
||||
void onWebsocketMessage(esp_websocket_event_data_t *event_data) {
|
||||
SpiRamJsonDocument doc(event_data->data_len);
|
||||
JsonDocument doc;
|
||||
|
||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||
|
||||
JsonDocument filter;
|
||||
filter["block"]["height"] = true;
|
||||
filter["mempool-blocks"][0]["medianFee"] = true;
|
||||
|
||||
DeserializationError error = deserializeJson(doc, (char *)event_data->data_ptr, DeserializationOption::Filter(filter));
|
||||
|
||||
// if (error) {
|
||||
// Serial.print("deserializeJson() failed: ");
|
||||
// Serial.println(error.c_str());
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (doc.containsKey("block")) {
|
||||
JsonObject block = doc["block"];
|
||||
|
||||
currentBlockHeight = block["height"].as<uint>();
|
||||
|
||||
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
||||
//Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
||||
preferences.putUInt("blockHeight", currentBlockHeight);
|
||||
|
||||
if (workQueue != nullptr) {
|
||||
|
@ -167,6 +179,23 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data) {
|
|||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||
}
|
||||
}
|
||||
} else if (doc.containsKey("mempool-blocks")) {
|
||||
JsonArray blockInfo = doc["mempool-blocks"].as<JsonArray>();
|
||||
|
||||
uint medianFee = (uint)round(blockInfo[0]["medianFee"].as<double>());
|
||||
|
||||
if (blockMedianFee == medianFee) {
|
||||
doc.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Serial.printf("New median fee: %d\r\n", medianFee);
|
||||
blockMedianFee = medianFee;
|
||||
|
||||
if (workQueue != nullptr) {
|
||||
WorkItem blockUpdate = {TASK_FEE_UPDATE, 0};
|
||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
doc.clear();
|
||||
|
@ -178,6 +207,12 @@ void setBlockHeight(uint newBlockHeight) {
|
|||
currentBlockHeight = newBlockHeight;
|
||||
}
|
||||
|
||||
uint getBlockMedianFee() { return blockMedianFee; }
|
||||
|
||||
void setBlockMedianFee(uint newBlockMedianFee) {
|
||||
blockMedianFee = newBlockMedianFee;
|
||||
}
|
||||
|
||||
bool isBlockNotifyConnected() {
|
||||
if (blockNotifyClient == NULL) return false;
|
||||
return esp_websocket_client_is_connected(blockNotifyClient);
|
||||
|
|
|
@ -23,6 +23,10 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data);
|
|||
|
||||
void setBlockHeight(uint newBlockHeight);
|
||||
uint getBlockHeight();
|
||||
|
||||
void setBlockMedianFee(uint blockMedianFee);
|
||||
uint getBlockMedianFee();
|
||||
|
||||
bool isBlockNotifyConnected();
|
||||
void stopBlockNotify();
|
||||
bool getBlockNotifyInit();
|
|
@ -208,6 +208,7 @@ void setupPreferences()
|
|||
setPrice(preferences.getUInt("lastPrice", 30000));
|
||||
|
||||
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";
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once;
|
||||
#pragma once
|
||||
|
||||
#include <Adafruit_MCP23X17.h>
|
||||
#include <Arduino.h>
|
||||
#include <Preferences.h>
|
||||
|
|
|
@ -85,13 +85,13 @@ void downloadUpdate() {
|
|||
if (httpCode == 200) {
|
||||
// WiFiClient * stream = http->getStreamPtr();
|
||||
|
||||
StaticJsonDocument<64> filter;
|
||||
JsonDocument filter;
|
||||
|
||||
JsonObject filter_assets_0 = filter["assets"].createNestedObject();
|
||||
JsonObject filter_assets_0 = filter["assets"].add<JsonObject>();
|
||||
filter_assets_0["name"] = true;
|
||||
filter_assets_0["browser_download_url"] = true;
|
||||
|
||||
SpiRamJsonDocument doc(1536);
|
||||
JsonDocument doc;
|
||||
|
||||
DeserializationError error = deserializeJson(
|
||||
doc, http.getStream(), DeserializationOption::Filter(filter));
|
||||
|
|
|
@ -24,7 +24,7 @@ void taskPriceFetch(void *pvParameters) {
|
|||
uint usdPrice, eurPrice;
|
||||
if (httpCode == 200) {
|
||||
String payload = http->getString();
|
||||
StaticJsonDocument<96> doc;
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, payload);
|
||||
// usdPrice = doc["bitcoin"]["usd"];
|
||||
eurPrice = doc["bitcoin"]["eur"].as<uint>();
|
||||
|
|
|
@ -76,7 +76,7 @@ void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
|
|||
}
|
||||
|
||||
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
|
||||
SpiRamJsonDocument doc(event_data->data_len);
|
||||
JsonDocument doc;
|
||||
|
||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||
|
||||
|
|
|
@ -46,6 +46,13 @@ void workerTask(void *pvParameters) {
|
|||
setEpdContent(taskEpdContent);
|
||||
break;
|
||||
}
|
||||
case TASK_FEE_UPDATE: {
|
||||
if (getCurrentScreen() == SCREEN_BLOCK_FEE_RATE) {
|
||||
taskEpdContent = parseBlockFees(static_cast<std::uint16_t>(getBlockMedianFee()));
|
||||
setEpdContent(taskEpdContent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TASK_BLOCK_UPDATE: {
|
||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||
|
|
|
@ -24,6 +24,7 @@ extern QueueHandle_t workQueue;
|
|||
typedef enum {
|
||||
TASK_PRICE_UPDATE,
|
||||
TASK_BLOCK_UPDATE,
|
||||
TASK_FEE_UPDATE,
|
||||
TASK_TIME_UPDATE
|
||||
} TaskType;
|
||||
|
||||
|
|
|
@ -22,26 +22,28 @@ 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_BLOCK_FEE_RATE = 6;
|
||||
|
||||
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
||||
const PROGMEM int SCREEN_CUSTOM = 99;
|
||||
const int SCREEN_COUNT = 6;
|
||||
const int SCREEN_COUNT = 7;
|
||||
const PROGMEM int screens[SCREEN_COUNT] = {
|
||||
SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER,
|
||||
SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP};
|
||||
SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP,
|
||||
SCREEN_BLOCK_FEE_RATE};
|
||||
const int usPerSecond = 1000000;
|
||||
const int usPerMinute = 60 * usPerSecond;
|
||||
|
||||
struct SpiRamAllocator {
|
||||
void *allocate(size_t size) {
|
||||
struct SpiRamAllocator : ArduinoJson::Allocator {
|
||||
void* allocate(size_t size) override {
|
||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
void deallocate(void *pointer) { heap_caps_free(pointer); }
|
||||
void deallocate(void* pointer) override {
|
||||
heap_caps_free(pointer);
|
||||
}
|
||||
|
||||
void *reallocate(void *ptr, size_t new_size) {
|
||||
void* reallocate(void* ptr, size_t new_size) override {
|
||||
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
};
|
||||
|
||||
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
||||
};
|
|
@ -94,8 +94,8 @@ void setupWebserver() {
|
|||
|
||||
void stopWebServer() { server.end(); }
|
||||
|
||||
StaticJsonDocument<768> getStatusObject() {
|
||||
StaticJsonDocument<768> root;
|
||||
JsonDocument getStatusObject() {
|
||||
JsonDocument root;
|
||||
|
||||
root["currentScreen"] = getCurrentScreen();
|
||||
root["numScreens"] = NUM_SCREENS;
|
||||
|
@ -108,7 +108,7 @@ StaticJsonDocument<768> getStatusObject() {
|
|||
// root["espFreePsram"] = ESP.getFreePsram();
|
||||
// root["espPsramSize"] = ESP.getPsramSize();
|
||||
|
||||
JsonObject conStatus = root.createNestedObject("connectionStatus");
|
||||
JsonObject conStatus = root["connectionStatus"].to<JsonObject>();
|
||||
conStatus["price"] = isPriceNotifyConnected();
|
||||
conStatus["blocks"] = isBlockNotifyConnected();
|
||||
|
||||
|
@ -117,9 +117,9 @@ StaticJsonDocument<768> getStatusObject() {
|
|||
return root;
|
||||
}
|
||||
|
||||
StaticJsonDocument<512> getLedStatusObject() {
|
||||
StaticJsonDocument<512> root;
|
||||
JsonArray colors = root.createNestedArray("data");
|
||||
JsonDocument getLedStatusObject() {
|
||||
JsonDocument root;
|
||||
JsonArray colors = root["data"].to<JsonArray>();
|
||||
// Adafruit_NeoPixel pix = getPixels();
|
||||
|
||||
for (uint i = 0; i < pixels.numPixels(); i++) {
|
||||
|
@ -131,7 +131,7 @@ StaticJsonDocument<512> getLedStatusObject() {
|
|||
char hexColor[8];
|
||||
sprintf(hexColor, "#%02X%02X%02X", red, green, blue);
|
||||
|
||||
JsonObject object = colors.createNestedObject();
|
||||
JsonObject object = colors.add<JsonObject>();
|
||||
object["red"] = red;
|
||||
object["green"] = green;
|
||||
object["blue"] = blue;
|
||||
|
@ -143,8 +143,8 @@ StaticJsonDocument<512> getLedStatusObject() {
|
|||
|
||||
void eventSourceUpdate() {
|
||||
if (!events.count()) return;
|
||||
StaticJsonDocument<768> root = getStatusObject();
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonDocument root = getStatusObject();
|
||||
JsonArray data = root["data"].to<JsonArray>();
|
||||
|
||||
root["leds"] = getLedStatusObject()["data"];
|
||||
|
||||
|
@ -168,9 +168,9 @@ void onApiStatus(AsyncWebServerRequest *request) {
|
|||
AsyncResponseStream *response =
|
||||
request->beginResponseStream("application/json");
|
||||
|
||||
StaticJsonDocument<1024> root = getStatusObject();
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonArray rendered = root.createNestedArray("rendered");
|
||||
JsonDocument root = getStatusObject();
|
||||
JsonArray data = root["data"].to<JsonArray>();
|
||||
JsonArray rendered = root["rendered"].to<JsonArray>();
|
||||
String epdContent[NUM_SCREENS];
|
||||
|
||||
root["leds"] = getLedStatusObject()["data"];
|
||||
|
@ -384,7 +384,7 @@ void onApiRestart(AsyncWebServerRequest *request) {
|
|||
* @Path("/api/settings")
|
||||
*/
|
||||
void onApiSettingsGet(AsyncWebServerRequest *request) {
|
||||
StaticJsonDocument<1536> root;
|
||||
JsonDocument root;
|
||||
root["numScreens"] = NUM_SCREENS;
|
||||
root["fgColor"] = getFgColor();
|
||||
root["bgColor"] = getBgColor();
|
||||
|
@ -421,12 +421,12 @@ void onApiSettingsGet(AsyncWebServerRequest *request) {
|
|||
#ifdef LAST_BUILD_TIME
|
||||
root["lastBuildTime"] = String(LAST_BUILD_TIME);
|
||||
#endif
|
||||
JsonArray screens = root.createNestedArray("screens");
|
||||
JsonArray screens = root["screens"].to<JsonArray>();
|
||||
|
||||
std::vector<std::string> screenNameMap = getScreenNameMap();
|
||||
|
||||
for (int i = 0; i < screenNameMap.size(); i++) {
|
||||
JsonObject o = screens.createNestedObject();
|
||||
JsonObject o = screens.add<JsonObject>();
|
||||
String key = "screen" + String(i) + "Visible";
|
||||
o["id"] = i;
|
||||
o["name"] = screenNameMap[i];
|
||||
|
@ -650,7 +650,7 @@ void onApiSystemStatus(AsyncWebServerRequest *request) {
|
|||
AsyncResponseStream *response =
|
||||
request->beginResponseStream("application/json");
|
||||
|
||||
StaticJsonDocument<128> root;
|
||||
JsonDocument root;
|
||||
|
||||
root["espFreeHeap"] = ESP.getFreeHeap();
|
||||
root["espHeapSize"] = ESP.getHeapSize();
|
||||
|
@ -743,7 +743,7 @@ void onApiLightsSetColor(AsyncWebServerRequest *request) {
|
|||
setLights(r, g, b);
|
||||
}
|
||||
|
||||
StaticJsonDocument<48> doc;
|
||||
JsonDocument doc;
|
||||
doc["result"] = rgbColor;
|
||||
|
||||
serializeJson(getLedStatusObject()["data"], *response);
|
||||
|
|
|
@ -46,8 +46,8 @@ void onApiRestart(AsyncWebServerRequest *request);
|
|||
void onIndex(AsyncWebServerRequest *request);
|
||||
void onNotFound(AsyncWebServerRequest *request);
|
||||
|
||||
StaticJsonDocument<512> getLedStatusObject();
|
||||
StaticJsonDocument<768> getStatusObject();
|
||||
JsonDocument getLedStatusObject();
|
||||
JsonDocument getStatusObject();
|
||||
void eventSourceUpdate();
|
||||
void eventSourceTask(void *pvParameters);
|
||||
|
||||
|
|
|
@ -31,6 +31,16 @@ void test_SevenCharacterBlockHeight(void) {
|
|||
TEST_ASSERT_EQUAL_STRING("0", output[1].c_str());
|
||||
}
|
||||
|
||||
void test_FeeRateDisplay(void) {
|
||||
uint testValue = 21;
|
||||
std::array<std::string, NUM_SCREENS> output = parseBlockFees(static_cast<std::uint16_t>(testValue));
|
||||
TEST_ASSERT_EQUAL_STRING("FEE/RATE", output[0].c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("2", output[NUM_SCREENS-3].c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("1", output[NUM_SCREENS-2].c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("sat/vB", output[NUM_SCREENS-1].c_str());
|
||||
}
|
||||
|
||||
|
||||
void test_PriceOf100kusd(void) {
|
||||
std::array<std::string, NUM_SCREENS> output = parsePriceData(100000, '$');
|
||||
TEST_ASSERT_EQUAL_STRING("$", output[0].c_str());
|
||||
|
@ -89,6 +99,7 @@ int runUnityTests(void) {
|
|||
RUN_TEST(test_CorrectSatsPerDollarConversion);
|
||||
RUN_TEST(test_SixCharacterBlockHeight);
|
||||
RUN_TEST(test_SevenCharacterBlockHeight);
|
||||
RUN_TEST(test_FeeRateDisplay);
|
||||
RUN_TEST(test_PriceOf100kusd);
|
||||
RUN_TEST(test_McapLowerUsd);
|
||||
RUN_TEST(test_Mcap1TrillionUsd);
|
||||
|
|
Loading…
Reference in a new issue