Use own nostrduino fork, improve nostr code, WebUI update

This commit is contained in:
Djuri Baars 2024-12-26 21:43:50 +01:00
parent 957a947bc5
commit 66c662e1fd
3 changed files with 132 additions and 101 deletions

2
data

@ -1 +1 @@
Subproject commit 924be8fc2eb02fe384a20b53da1a9fa3d8db8a05
Subproject commit 65b6df5d92f3f936e823a5c1413681aee85ab0c5

View file

@ -43,7 +43,7 @@ lib_deps =
https://github.com/dsbaars/universal_pin#feature/mcp23017_rt
https://github.com/dsbaars/GxEPD2#universal_pin
https://github.com/tzapu/WiFiManager.git#v2.0.17
rblb/Nostrduino@1.2.8
https://github.com/dsbaars/nostrduino#feature/fix-btclock
[env:lolin_s3_mini]
extends = btclock_base
@ -71,7 +71,11 @@ board = btclock_rev_b
board_build.partitions = partition_8mb.csv
build_flags =
${btclock_base.build_flags}
-D MCP_INT_PIN=8
-D MCP_INT_PIN=8docker run --rm -e RENOVATE_TOKEN -e LOG_LEVEL=debug \
-e "RENOVATE_REPOSITORIES=[\"your-repo-name\"]" \
renovate/renovate \
--platform local \
--dry-run
-D NEOPIXEL_PIN=15
-D NEOPIXEL_COUNT=4
-D NUM_SCREENS=7

View file

@ -27,8 +27,8 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
String pubKey = preferences.getString("nostrPubKey");
pools.push_back(pool);
std::vector<std::map<NostrString, std::initializer_list<NostrString>>> filters;
std::vector<nostr::NostrRelay *> *relays = pool->getConnectedRelays();
if (zapNotify)
{
subscribeZaps(pool, relay, 60);
@ -46,31 +46,29 @@ void setupNostrNotify(bool asDatasource, bool zapNotify)
}},
handleNostrEventCallback,
onNostrSubscriptionClosed,
onNostrSubscriptionEose);
onNostrSubscriptionEose
);
Serial.println("[ Nostr ] Subscribing to Nostr Data Feed");
Serial.println(F("[ Nostr ] Subscribing to Nostr Data Feed"));
}
std::vector<nostr::NostrRelay *> *relays = pool->getConnectedRelays();
for (nostr::NostrRelay *relay : *relays)
{
Serial.println("[ Nostr ] Registering to connection events of: " + relay->getUrl());
relay->getConnection()->addConnectionStatusListener([&](const nostr::ConnectionStatus &status)
{
String sstatus="UNKNOWN";
if(status==nostr::ConnectionStatus::CONNECTED){
nostrIsConnected = true;
sstatus="CONNECTED";
}else if(status==nostr::ConnectionStatus::DISCONNECTED){
nostrIsConnected = false;
relay->getConnection()->addConnectionStatusListener([](const nostr::ConnectionStatus &status)
{
static const char* STATUS_STRINGS[] = {"UNKNOWN", "CONNECTED", "DISCONNECTED", "ERROR"};
int statusIndex = static_cast<int>(status);
nostrIsConnected = (status == nostr::ConnectionStatus::CONNECTED);
if (!nostrIsConnected) {
nostrIsSubscribed = false;
sstatus="DISCONNECTED";
}else if(status==nostr::ConnectionStatus::ERROR){
sstatus = "ERROR";
}
Serial.println("[ Nostr ] Connection status changed: " + sstatus);
});
Serial.println("[ Nostr ] Connection status changed: " + String(STATUS_STRINGS[statusIndex]));
});
}
}
catch (const std::exception &e)
{
@ -103,7 +101,7 @@ void nostrTask(void *pvParameters)
void setupNostrTask()
{
xTaskCreate(nostrTask, "nostrTask", 16384, NULL, 10, &nostrTaskHandle);
xTaskCreate(nostrTask, "nostrTask", 8192, NULL, 10, &nostrTaskHandle);
}
boolean nostrConnected()
@ -129,55 +127,57 @@ void onNostrSubscriptionEose(const String &subId)
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
// Early return if array is invalid
if (arr.size() < 2 || !arr[1].is<JsonObject>()) {
return;
}
JsonObject obj = arr[1].as<JsonObject>();
JsonArray tags = obj["tags"].as<JsonArray>();
if (!tags) {
return;
}
// Flag to check if the tag was found
bool tagFound = false;
uint medianFee = 0;
// Use direct value access instead of multiple comparisons
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>();
}
uint medianFee = 0;
for (JsonArray tag : tags) {
if (tag.size() != 2) continue;
const char *key = tag[0];
if (!key) continue;
// Use switch for better performance on string comparisons
switch (key[0]) {
case 't': // type
if (strcmp(key, "type") == 0) {
const char *value = tag[1];
if (value) typeValue = value;
}
break;
case 'm': // medianFee
if (strcmp(key, "medianFee") == 0) {
medianFee = tag[1].as<uint>();
}
break;
}
}
if (tagFound)
{
if (typeValue.equals("priceUsd"))
{
// Process the data
if (!typeValue.isEmpty()) {
if (typeValue == "priceUsd") {
processNewPrice(obj["content"].as<uint>(), CURRENCY_USD);
}
else if (typeValue.equals("blockHeight"))
{
else if (typeValue == "blockHeight") {
processNewBlock(obj["content"].as<uint>());
}
if (medianFee != 0)
{
if (medianFee != 0) {
processNewBlockFee(medianFee);
}
}
@ -202,7 +202,27 @@ void subscribeZaps(nostr::NostrPool *pool, const String &relay, int minutesAgo)
{"kinds", {"9735"}},
{"limit", {"1"}},
{"since", {String(getMinutesAgo(minutesAgo))}},
{"#p", {preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY)}},
{"#p", {preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY) }},
// {"#p", [&]() {
// std::initializer_list<NostrString> pubkeys;
// String pubkeysStr = preferences.getString("nostrZapPubkeys", "");
// if (pubkeysStr.length() > 0) {
// // Assuming pubkeys are comma-separated
// char* str = strdup(pubkeysStr.c_str());
// char* token = strtok(str, ",");
// std::vector<NostrString> keys;
// while (token != NULL) {
// keys.push_back(String(token));
// token = strtok(NULL, ",");
// }
// free(str);
// return std::initializer_list<NostrString>(keys.begin(), keys.end());
// }
// // Return default if no pubkeys found
// return std::initializer_list<NostrString>{
// preferences.getString("nostrZapPubkey", DEFAULT_ZAP_NOTIFY_PUBKEY)
// };
// }()},
},
},
handleNostrZapCallback,
@ -212,56 +232,63 @@ void subscribeZaps(nostr::NostrPool *pool, const String &relay, int minutesAgo)
}
void handleNostrZapCallback(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
// Early return if invalid
if (arr.size() < 2 || !arr[1].is<JsonObject>()) {
return;
}
JsonObject obj = arr[1].as<JsonObject>();
JsonArray tags = obj["tags"].as<JsonArray>();
if (!tags) {
return;
}
// 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];
uint64_t zapAmount = 0;
String zapPubkey;
for (JsonArray tag : tags) {
if (tag.size() != 2) continue;
const char *key = tag[0];
const char *value = tag[1];
if (!key || !value) continue;
if (strcmp(key, "bolt11") == 0)
{
Serial.print(F("Got a zap of "));
int64_t satsAmount = getAmountInSatoshis(std::string(value));
Serial.print(satsAmount);
Serial.println(F(" sats"));
std::array<std::string, NUM_SCREENS> textEpdContent = parseZapNotify(satsAmount, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
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));
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
{
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
}
if (timerPeriod > 0)
{
esp_timer_start_periodic(screenRotateTimer,
timerPeriod * usPerSecond);
}
}
if (key[0] == 'b' && strcmp(key, "bolt11") == 0) {
zapAmount = getAmountInSatoshis(std::string(value));
}
else if (key[0] == 'p' && strcmp(key, "p") == 0) {
zapPubkey = value;
}
}
if (zapAmount == 0) return;
std::array<std::string, NUM_SCREENS> textEpdContent = parseZapNotify(zapAmount, preferences.getBool("useSatsSymbol", DEFAULT_USE_SATS_SYMBOL));
Serial.printf("Got a zap of %llu sats for %s\n", zapAmount, zapPubkey.c_str());
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));
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
{
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
}
if (timerPeriod > 0)
{
esp_timer_start_periodic(screenRotateTimer,
timerPeriod * usPerSecond);
}
}