Add zap notify functionality
This commit is contained in:
parent
99e622eeef
commit
e39a0ccc14
13 changed files with 506 additions and 78 deletions
|
@ -72,12 +72,13 @@ void setup()
|
|||
setupTasks();
|
||||
setupTimers();
|
||||
|
||||
if (preferences.getBool("useNostr", DEFAULT_USE_NOSTR))
|
||||
if (preferences.getBool("useNostr", DEFAULT_USE_NOSTR) || preferences.getBool("nostrZapNotify", DEFAULT_ZAP_NOTIFY_ENABLED))
|
||||
{
|
||||
setupNostrNotify();
|
||||
setupNostrTask();
|
||||
}
|
||||
else
|
||||
|
||||
if (!preferences.getBool("useNostr", DEFAULT_USE_NOSTR))
|
||||
{
|
||||
xTaskCreate(setupWebsocketClients, "setupWebsocketClients", 8192, NULL,
|
||||
tskIDLE_PRIORITY, NULL);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#define DEFAULT_USE_NOSTR false
|
||||
#define DEFAULT_NOSTR_NPUB "642317135fd4c4205323b9dea8af3270657e62d51dc31a657c0ec8aab31c6288"
|
||||
#define DEFAULT_NOSTR_RELAY "wss://nostr.dbtc.link"
|
||||
#define DEFAULT_NOSTR_RELAY "wss://relay.primal.net"
|
||||
|
||||
#define DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE 30
|
||||
#define DEFAULT_MINUTES_FULL_REFRESH 60
|
||||
|
@ -49,3 +49,5 @@
|
|||
#define DEFAULT_BITAXE_ENABLED false
|
||||
#define DEFAULT_BITAXE_HOSTNAME "bitaxe1"
|
||||
|
||||
#define DEFAULT_ZAP_NOTIFY_ENABLED false
|
||||
#define DEFAULT_ZAP_NOTIFY_PUBKEY "b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422"
|
|
@ -531,6 +531,10 @@ void renderIcon(const uint dispNum, const String &text, bool partial)
|
|||
iconIndex = 1;
|
||||
}
|
||||
|
||||
if (text.endsWith("lnbolt")) {
|
||||
iconIndex = 2;
|
||||
}
|
||||
|
||||
displays[dispNum].drawInvertedBitmap(0,0, epd_icons_allArray[iconIndex], 122, 250, getFgColor());
|
||||
|
||||
}
|
||||
|
|
|
@ -221,9 +221,9 @@ void ledTask(void *parameter)
|
|||
{
|
||||
oldLights[i] = pixels.getPixelColor(i);
|
||||
}
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
uint flDelayTime = preferences.getUInt("flEffectDelay");
|
||||
#endif
|
||||
#endif
|
||||
switch (ledTaskParams)
|
||||
{
|
||||
case LED_POWER_TEST:
|
||||
|
@ -269,6 +269,43 @@ void ledTask(void *parameter)
|
|||
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
||||
pixels.show();
|
||||
break;
|
||||
case LED_EFFECT_NOSTR_ZAP:
|
||||
{
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
bool frontlightWasOn = false;
|
||||
|
||||
if (preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
|
||||
{
|
||||
if (frontlightOn)
|
||||
{
|
||||
frontlightWasOn = true;
|
||||
frontlightFadeOutAll(flDelayTime, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
frontlightFadeInAll(flDelayTime, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
blinkDelayColor(250, 3, 142, 48, 235);
|
||||
// blinkDelayTwoColor(250, 3, pixels.Color(142, 48, 235),
|
||||
// pixels.Color(169, 21, 255));
|
||||
#ifdef HAS_FRONTLIGHT
|
||||
if (preferences.getBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE))
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
if (frontlightWasOn)
|
||||
{
|
||||
frontlightFadeInAll(flDelayTime, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
frontlightFadeOutAll(flDelayTime, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case LED_FLASH_UPDATE:
|
||||
break;
|
||||
case LED_FLASH_BLOCK_NOTIFY:
|
||||
|
|
|
@ -28,6 +28,7 @@ const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
|
|||
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
||||
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
||||
|
||||
|
||||
const int LED_PROGRESS_25 = 200;
|
||||
const int LED_PROGRESS_50 = 201;
|
||||
const int LED_PROGRESS_75 = 202;
|
||||
|
@ -35,6 +36,9 @@ const int LED_PROGRESS_100 = 203;
|
|||
|
||||
const int LED_DATA_PRICE_ERROR = 300;
|
||||
const int LED_DATA_BLOCK_ERROR = 301;
|
||||
|
||||
const int LED_EFFECT_NOSTR_ZAP = 400;
|
||||
|
||||
const int LED_FLASH_IDENTIFY = 990;
|
||||
const int LED_POWER_TEST = 999;
|
||||
extern TaskHandle_t ledTaskHandle;
|
||||
|
|
|
@ -22,71 +22,33 @@ void setupNostrNotify()
|
|||
String relay = preferences.getString("nostrRelay");
|
||||
String pubKey = preferences.getString("nostrPubKey");
|
||||
pools.push_back(pool);
|
||||
|
||||
// JsonArray filter = {
|
||||
// {"kinds", {"1"}},
|
||||
// {"since", {String(timestamp60MinutesAgo)}},
|
||||
// {"authors", {pubKey}},
|
||||
// };
|
||||
|
||||
// { "kinds", {"9735"}, {"limit",{"1"},
|
||||
// {"#p", {"b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422"} },
|
||||
|
||||
// Lets subscribe to the relay
|
||||
String subId = pool->subscribeMany(
|
||||
{relay},
|
||||
{{// we set the filters here (see
|
||||
// https://github.com/nostr-protocol/nips/blob/master/01.md#from-client-to-relay-sending-events-and-creating-subscriptions)
|
||||
{"kinds", {"1"}},
|
||||
{"since", {String(timestamp60MinutesAgo)}},
|
||||
{"authors", {pubKey}}}},
|
||||
[&](const String &subId, nostr::SignedNostrEvent *event)
|
||||
{
|
||||
// Received events callback, we can access the event content with
|
||||
// event->getContent() Here you should handle the event, for this
|
||||
// test we will just serialize it and print to console
|
||||
JsonDocument doc;
|
||||
JsonArray arr = doc["data"].to<JsonArray>();
|
||||
event->toSendableEvent(arr);
|
||||
// Access the second element which is the object
|
||||
JsonObject obj = arr[1].as<JsonObject>();
|
||||
|
||||
// Access the "tags" array
|
||||
JsonArray tags = obj["tags"].as<JsonArray>();
|
||||
|
||||
// Flag to check if the tag was found
|
||||
bool tagFound = false;
|
||||
uint medianFee = 0;
|
||||
String typeValue;
|
||||
|
||||
// Iterate over the tags array
|
||||
for (JsonArray tag : tags)
|
||||
{
|
||||
// Check if the tag is an array with two elements
|
||||
if (tag.size() == 2)
|
||||
{
|
||||
const char *key = tag[0];
|
||||
const char *value = tag[1];
|
||||
|
||||
// Check if the key is "type" and the value is "priceUsd"
|
||||
if (strcmp(key, "type") == 0 && (strcmp(value, "priceUsd") == 0 || strcmp(value, "blockHeight") == 0))
|
||||
{
|
||||
typeValue = value;
|
||||
tagFound = true;
|
||||
}
|
||||
else if (strcmp(key, "medianFee") == 0)
|
||||
{
|
||||
medianFee = tag[1].as<uint>();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tagFound)
|
||||
{
|
||||
if (typeValue.equals("priceUsd"))
|
||||
{
|
||||
processNewPrice(obj["content"].as<uint>());
|
||||
}
|
||||
else if (typeValue.equals("blockHeight"))
|
||||
{
|
||||
processNewBlock(obj["content"].as<uint>());
|
||||
}
|
||||
|
||||
if (medianFee != 0)
|
||||
{
|
||||
processNewBlockFee(medianFee);
|
||||
}
|
||||
}
|
||||
},
|
||||
{// First filter
|
||||
{
|
||||
{"kinds", {"9735"}},
|
||||
{"limit", {"1"}},
|
||||
{"since", {String(timestamp60MinutesAgo)}},
|
||||
{"#p", {preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY)}},
|
||||
},
|
||||
// Second filter
|
||||
{
|
||||
{"kinds", {"1"}},
|
||||
{"since", {String(timestamp60MinutesAgo)}},
|
||||
{"authors", {pubKey}},
|
||||
}},
|
||||
handleNostrEventCallback,
|
||||
[&](const String &subId, const String &reason)
|
||||
{
|
||||
// This is the callback that will be called when the subscription is
|
||||
|
@ -150,4 +112,109 @@ void setupNostrTask()
|
|||
boolean nostrConnected()
|
||||
{
|
||||
return nostrIsConnected;
|
||||
}
|
||||
|
||||
void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *event)
|
||||
{
|
||||
// Received events callback, we can access the event content with
|
||||
// event->getContent() Here you should handle the event, for this
|
||||
// test we will just serialize it and print to console
|
||||
JsonDocument doc;
|
||||
JsonArray arr = doc["data"].to<JsonArray>();
|
||||
event->toSendableEvent(arr);
|
||||
// Access the second element which is the object
|
||||
JsonObject obj = arr[1].as<JsonObject>();
|
||||
String json;
|
||||
|
||||
// Serial.println(obj["kind"].as<String>());
|
||||
|
||||
// Access the "tags" array
|
||||
JsonArray tags = obj["tags"].as<JsonArray>();
|
||||
|
||||
// Flag to check if the tag was found
|
||||
bool tagFound = false;
|
||||
uint medianFee = 0;
|
||||
String typeValue;
|
||||
|
||||
// Iterate over the tags array
|
||||
for (JsonArray tag : tags)
|
||||
{
|
||||
// Check if the tag is an array with two elements
|
||||
if (tag.size() == 2)
|
||||
{
|
||||
const char *key = tag[0];
|
||||
const char *value = tag[1];
|
||||
|
||||
// Check if the key is "type" and the value is "priceUsd"
|
||||
if (strcmp(key, "type") == 0 && (strcmp(value, "priceUsd") == 0 || strcmp(value, "blockHeight") == 0))
|
||||
{
|
||||
typeValue = value;
|
||||
tagFound = true;
|
||||
}
|
||||
else if (strcmp(key, "medianFee") == 0)
|
||||
{
|
||||
medianFee = tag[1].as<uint>();
|
||||
}
|
||||
|
||||
if (strcmp(key, "bolt11") == 0)
|
||||
{
|
||||
|
||||
String text = String(getAmountInSatoshis(std::string(value)));
|
||||
|
||||
std::size_t textLength = text.length();
|
||||
|
||||
// Calculate the position where the digits should start
|
||||
// Account for the position of the "mdi:pickaxe" and the "GH/S" label
|
||||
std::size_t startIndex = NUM_SCREENS - textLength;
|
||||
|
||||
std::array<String, NUM_SCREENS> textEpdContent = {"ZAP", "mdi-lnbolt", "", "", "", "", ""};
|
||||
|
||||
// Insert the "mdi:pickaxe" icon just before the digits
|
||||
if (startIndex > 0 && preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL))
|
||||
{
|
||||
textEpdContent[startIndex - 1] = "STS";
|
||||
}
|
||||
|
||||
// Place the digits
|
||||
for (std::size_t i = 0; i < textLength; i++)
|
||||
{
|
||||
textEpdContent[startIndex + i] = text.substring(i, i + 1);
|
||||
}
|
||||
|
||||
uint64_t timerPeriod = 0;
|
||||
if (isTimerActive())
|
||||
{
|
||||
// store timer periode before making inactive to prevent artifacts
|
||||
timerPeriod = getTimerSeconds();
|
||||
esp_timer_stop(screenRotateTimer);
|
||||
}
|
||||
setCurrentScreen(SCREEN_CUSTOM);
|
||||
|
||||
setEpdContent(textEpdContent);
|
||||
vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250));
|
||||
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
|
||||
if (timerPeriod > 0)
|
||||
{
|
||||
esp_timer_start_periodic(screenRotateTimer,
|
||||
timerPeriod * usPerSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tagFound)
|
||||
{
|
||||
if (typeValue.equals("priceUsd"))
|
||||
{
|
||||
processNewPrice(obj["content"].as<uint>());
|
||||
}
|
||||
else if (typeValue.equals("blockHeight"))
|
||||
{
|
||||
processNewBlock(obj["content"].as<uint>());
|
||||
}
|
||||
|
||||
if (medianFee != 0)
|
||||
{
|
||||
processNewBlockFee(medianFee);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,4 +15,5 @@ void setupNostrNotify();
|
|||
void nostrTask(void *pvParameters);
|
||||
void setupNostrTask();
|
||||
|
||||
boolean nostrConnected();
|
||||
boolean nostrConnected();
|
||||
void handleNostrEventCallback(const String &subId, nostr::SignedNostrEvent *event);
|
|
@ -443,7 +443,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
|||
settings["timePerScreen"].as<uint>() * 60);
|
||||
}
|
||||
|
||||
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname"};
|
||||
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "nostrZapPubkey"};
|
||||
|
||||
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", "bitaxeEnabled"};
|
||||
"suffixPrice", "disableLeds", "ownDataSource", "flAlwaysOn", "flFlashOnUpd", "mempoolSecure", "useNostr", "bitaxeEnabled", "nostrZapNotify"};
|
||||
|
||||
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["nostrZapNotify"] = preferences.getBool("nostrZapNotify", DEFAULT_ZAP_NOTIFY_ENABLED);
|
||||
root["nostrZapPubkey"] = preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY);
|
||||
|
||||
root["bitaxeEnabled"] = preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED);
|
||||
root["bitaxeHostname"] = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue