forked from btclock/btclock_v3
Added EventSource for webUI updates, completed more features
This commit is contained in:
parent
91fd921e2e
commit
280764a2fa
16 changed files with 241 additions and 78 deletions
|
@ -172,8 +172,8 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<label for="tzOffset" class="col-sm-6 col-form-label">Timezone offset</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group mb-3">
|
||||
<div class="col-sm-6 mb-3">
|
||||
<div class="input-group">
|
||||
<input type="number" name="tzOffset" id="tzOffset" class="form-control">
|
||||
<span class="input-group-text">min</span>
|
||||
<button class="btn btn-outline-secondary" type="button" id="getTzOffsetBtn">Auto</button>
|
||||
|
@ -181,11 +181,21 @@
|
|||
<div class="form-text">A restart is required to apply TZ offset.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label for="minSecPriceUpd" class="col-sm-6 col-form-label">Time between price updates</label>
|
||||
<div class="col-sm-6 mb-3">
|
||||
<div class="input-group">
|
||||
<input type="number" name="minSecPriceUpd" id="minSecPriceUpd" class="form-control">
|
||||
<span class="input-group-text">sec</span>
|
||||
</div>
|
||||
<div class="form-text">Short amounts might shorten lifespan.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class=" col-sm-6">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="ledFlashOnUpdate" name="ledFlashOnUpd" value="1">
|
||||
<label class="form-check-label" for="ledFlashOnUpdate">LED flash on update</label>
|
||||
<label class="form-check-label" for="ledFlashOnUpdate">LED flash on new block</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -19,39 +19,65 @@ toTime = (secs) => {
|
|||
return obj;
|
||||
}
|
||||
|
||||
getBcStatus = () => {
|
||||
fetch('/api/status', {
|
||||
method: 'get'
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(jsonData => {
|
||||
var source = document.getElementById("entry-template").innerHTML;
|
||||
var template = Handlebars.compile(source);
|
||||
let processStatusData = (jsonData) => {
|
||||
var source = document.getElementById("entry-template").innerHTML;
|
||||
var template = Handlebars.compile(source);
|
||||
|
||||
var context = {
|
||||
timerRunning: jsonData.timerRunning,
|
||||
memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100),
|
||||
memFree: Math.round(jsonData.espFreeHeap / 1024),
|
||||
memTotal: Math.round(jsonData.espHeapSize / 1024),
|
||||
uptime: toTime(jsonData.espUptime),
|
||||
currentScreen: jsonData.currentScreen,
|
||||
rendered: jsonData.rendered,
|
||||
data: jsonData.data,
|
||||
screens: screens,
|
||||
ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [],
|
||||
connectionStatus: jsonData.connectionStatus
|
||||
};
|
||||
var context = {
|
||||
timerRunning: jsonData.timerRunning,
|
||||
memUsage: Math.round(jsonData.espFreeHeap / jsonData.espHeapSize * 100),
|
||||
memFree: Math.round(jsonData.espFreeHeap / 1024),
|
||||
memTotal: Math.round(jsonData.espHeapSize / 1024),
|
||||
uptime: toTime(jsonData.espUptime),
|
||||
currentScreen: jsonData.currentScreen,
|
||||
rendered: jsonData.data,
|
||||
data: jsonData.data,
|
||||
screens: screens,
|
||||
ledStatus: jsonData.ledStatus ? jsonData.ledStatus.map((t) => (t).toString(16)) : [],
|
||||
connectionStatus: jsonData.connectionStatus
|
||||
};
|
||||
|
||||
|
||||
document.getElementById('output').innerHTML = template(context);
|
||||
})
|
||||
.catch(err => {
|
||||
//error block
|
||||
});
|
||||
document.getElementById('output').innerHTML = template(context);
|
||||
}
|
||||
|
||||
interval = setInterval(getBcStatus, 2500);
|
||||
getBcStatus();
|
||||
|
||||
if (!!window.EventSource) {
|
||||
var source = new EventSource('/events');
|
||||
|
||||
source.addEventListener('open', function (e) {
|
||||
console.log("Status EventSource Connected");
|
||||
if (e.data) {
|
||||
processStatusData(JSON.parse(e.data));
|
||||
}
|
||||
}, false);
|
||||
|
||||
source.addEventListener('error', function (e) {
|
||||
if (e.target.readyState != EventSource.OPEN) {
|
||||
console.log("Status EventSource Disconnected");
|
||||
}
|
||||
source.close();
|
||||
}, false);
|
||||
|
||||
source.addEventListener('status', function (e) {
|
||||
processStatusData(JSON.parse(e.data));
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
// getBcStatus = () => {
|
||||
// fetch('/api/status', {
|
||||
// method: 'get'
|
||||
// })
|
||||
// .then(response => response.json())
|
||||
// .then()
|
||||
// .catch(err => {
|
||||
// //error block
|
||||
// });
|
||||
// }
|
||||
|
||||
// interval = setInterval(getBcStatus, 2500);
|
||||
// getBcStatus();
|
||||
|
||||
fetch('/api/settings', {
|
||||
method: 'get'
|
||||
|
@ -77,17 +103,18 @@ fetch('/api/settings', {
|
|||
if (jsonData.useBitcoinNode)
|
||||
document.getElementById('useBitcoinNode').checked = true;
|
||||
|
||||
let nodeFields = ["rpcHost", "rpcPort", "rpcUser", "tzOffset"];
|
||||
// let nodeFields = ["rpcHost", "rpcPort", "rpcUser", "tzOffset"];
|
||||
|
||||
for (let n of nodeFields) {
|
||||
document.getElementById(n).value = jsonData[n];
|
||||
}
|
||||
// for (let n of nodeFields) {
|
||||
// document.getElementById(n).value = jsonData[n];
|
||||
// }
|
||||
|
||||
document.getElementById('timePerScreen').value = jsonData.timerSeconds / 60;
|
||||
document.getElementById('ledBrightness').value = jsonData.ledBrightness;
|
||||
document.getElementById('fullRefreshMin').value = jsonData.fullRefreshMin;
|
||||
document.getElementById('wpTimeout').value = jsonData.wpTimeout;
|
||||
document.getElementById('tzOffset').value = jsonData.tzOffset;
|
||||
document.getElementById('mempoolInstance').value = jsonData.mempoolInstance;
|
||||
document.getElementById('minSecPriceUpd').value = jsonData.minSecPriceUpd;
|
||||
|
||||
if (jsonData.gitRev)
|
||||
document.getElementById('gitRev').innerHTML = "Version: " + jsonData.gitRev;
|
||||
|
|
|
@ -24,12 +24,11 @@ board_build.partitions = partition.csv
|
|||
build_flags =
|
||||
!python scripts/git_rev.py
|
||||
-DLAST_BUILD_TIME=$UNIX_TIME
|
||||
-DASYNCWEBSERVER_REGEX
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-DARDUINO_USB_CDC_ON_BOOT
|
||||
-fexceptions
|
||||
build_unflags =
|
||||
-fno-exceptions
|
||||
-Werror=all
|
||||
-fno-exceptions
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson@^6.21.3
|
||||
esphome/Improv@^1.2.3
|
||||
|
@ -48,4 +47,6 @@ build_flags =
|
|||
-D MCP_INT_PIN=8
|
||||
-D NEOPIXEL_PIN=34
|
||||
-D NEOPIXEL_COUNT=4
|
||||
-D NUM_SCREENS=7
|
||||
-D NUM_SCREENS=7
|
||||
build_unflags =
|
||||
${btclock_base.build_unflags}
|
||||
|
|
|
@ -32,7 +32,7 @@ void setupBlockNotify()
|
|||
{
|
||||
String blockHeightStr = http->getString();
|
||||
currentBlockHeight = blockHeightStr.toInt();
|
||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
}
|
||||
|
||||
// std::strcpy(wsServer, String("wss://" + mempoolInstance + "/api/v1/ws").c_str());
|
||||
|
@ -95,7 +95,10 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
|||
|
||||
if (blockUpdateTaskHandle != nullptr) {
|
||||
xTaskNotifyGive(blockUpdateTaskHandle);
|
||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||
if (preferences.getBool("ledFlashOnUpd", false)) {
|
||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ std::map<int, std::string> screenNameMap;
|
|||
|
||||
void setup()
|
||||
{
|
||||
setupPreferences();
|
||||
setupHardware();
|
||||
if (mcp.digitalRead(3) == LOW)
|
||||
{
|
||||
|
@ -20,7 +21,6 @@ void setup()
|
|||
setupDisplays();
|
||||
tryImprovSetup();
|
||||
|
||||
setupPreferences();
|
||||
setupWebserver();
|
||||
|
||||
// setupWifi();
|
||||
|
@ -112,7 +112,13 @@ void setupTimers()
|
|||
|
||||
void finishSetup()
|
||||
{
|
||||
clearLeds();
|
||||
|
||||
if (preferences.getBool("ledStatus", false)) {
|
||||
setLights(preferences.getUInt("ledColor", 0xFFCC00));
|
||||
} else {
|
||||
clearLeds();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::map<int, std::string> getScreenNameMap() {
|
||||
|
@ -122,7 +128,7 @@ std::map<int, std::string> getScreenNameMap() {
|
|||
void setupHardware()
|
||||
{
|
||||
setupLeds();
|
||||
|
||||
WiFi.setHostname(getMyHostname().c_str());;
|
||||
if (psramInit())
|
||||
{
|
||||
Serial.println(F("PSRAM is correctly initialized"));
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <esp_sntp.h>
|
||||
#include "epd.hpp"
|
||||
#include "improv.hpp"
|
||||
#include <map>
|
||||
|
||||
#include "lib/screen_handler.hpp"
|
||||
#include "lib/webserver.hpp"
|
||||
|
@ -22,6 +23,7 @@
|
|||
#define TIME_OFFSET_SECONDS 3600
|
||||
#define USER_AGENT "BTClock/2.0"
|
||||
#define MCP_DEV_ADDR 0x20
|
||||
#define DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE 30
|
||||
|
||||
#define DEFAULT_FG_COLOR GxEPD_WHITE
|
||||
#define DEFAULT_BG_COLOR GxEPD_BLACK
|
||||
|
|
|
@ -148,7 +148,16 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
|||
|
||||
if (epdContent[epdIndex].compareTo(currentEpdContent[epdIndex]) != 0)
|
||||
{
|
||||
|
||||
displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
||||
uint count = 0;
|
||||
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
if (count >= 9) {
|
||||
displays[epdIndex].init(0, false);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
bool updatePartial = true;
|
||||
|
||||
|
|
|
@ -185,20 +185,30 @@ void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2)
|
|||
|
||||
void clearLeds()
|
||||
{
|
||||
preferences.putBool("ledStatus", false);
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
void setLights(int r, int g, int b)
|
||||
{
|
||||
setLights(pixels.Color(r, g, b));
|
||||
}
|
||||
|
||||
void setLights(uint32_t color)
|
||||
{
|
||||
preferences.putUInt("ledColor", color);
|
||||
preferences.putBool("ledStatus", true);
|
||||
|
||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
||||
{
|
||||
pixels.setPixelColor(i, pixels.Color(r, g, b));
|
||||
pixels.setPixelColor(i, color);
|
||||
}
|
||||
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
|
||||
QueueHandle_t getLedTaskQueue()
|
||||
{
|
||||
return ledTaskQueue;
|
||||
|
|
|
@ -35,4 +35,5 @@ void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2);
|
|||
void clearLeds();
|
||||
QueueHandle_t getLedTaskQueue();
|
||||
bool queueLedEffect(uint effect);
|
||||
void setLights(int r, int g, int b);
|
||||
void setLights(int r, int g, int b);
|
||||
void setLights(uint32_t color);
|
|
@ -4,6 +4,7 @@ const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
|
|||
// WebsocketsClient client;
|
||||
esp_websocket_client_handle_t clientPrice = NULL;
|
||||
unsigned long int currentPrice;
|
||||
unsigned long int lastPriceUpdate = 0;
|
||||
|
||||
void setupPriceNotify()
|
||||
{
|
||||
|
@ -47,13 +48,19 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
|||
if (doc.containsKey("bitcoin")) {
|
||||
if (currentPrice != doc["bitcoin"].as<long>()) {
|
||||
|
||||
const unsigned long oldPrice = currentPrice;
|
||||
currentPrice = doc["bitcoin"].as<long>();
|
||||
uint minSecPriceUpd = preferences.getUInt("minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
||||
uint currentTime = esp_timer_get_time() / 1000000;
|
||||
|
||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||
if (priceUpdateTaskHandle != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME))
|
||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
||||
//}
|
||||
if (lastPriceUpdate == 0 || (currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
||||
// const unsigned long oldPrice = currentPrice;
|
||||
currentPrice = doc["bitcoin"].as<long>();
|
||||
|
||||
lastPriceUpdate = currentTime;
|
||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||
if (priceUpdateTaskHandle != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME))
|
||||
xTaskNotifyGive(priceUpdateTaskHandle);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,6 +180,8 @@ void setupTasks()
|
|||
xTaskCreate(taskBlockUpdate, "updateBlock", 2048, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
||||
xTaskCreate(taskTimeUpdate, "updateTime", 4096, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
||||
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
||||
|
||||
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
||||
}
|
||||
|
||||
void setupTimeUpdateTimer(void *pvParameters)
|
||||
|
@ -212,7 +214,10 @@ void setupScreenRotateTimer(void *pvParameters)
|
|||
.name = "screen_rotate_timer"};
|
||||
|
||||
esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer);
|
||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
||||
|
||||
if (preferences.getBool("timerActive", true)) {
|
||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
@ -233,11 +238,13 @@ void setTimerActive(bool status)
|
|||
{
|
||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
||||
queueLedEffect(LED_EFFECT_START_TIMER);
|
||||
preferences.putBool("timerActive", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
esp_timer_stop(screenRotateTimer);
|
||||
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
||||
preferences.putBool("timerActive", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,3 +4,9 @@ int modulo(int x, int N)
|
|||
{
|
||||
return (x % N + N) % N;
|
||||
}
|
||||
|
||||
String getMyHostname() {
|
||||
byte mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
return "btclock" + String(mac[4], 16) = String(mac[5], 16);
|
||||
}
|
|
@ -1 +1,7 @@
|
|||
int modulo(int x,int N);
|
||||
#pragma once
|
||||
|
||||
#include <WiFi.h>
|
||||
#include "shared.hpp"
|
||||
|
||||
int modulo(int x,int N);
|
||||
String getMyHostname();
|
|
@ -1,6 +1,7 @@
|
|||
#include "webserver.hpp"
|
||||
|
||||
AsyncWebServer server(80);
|
||||
AsyncEventSource events("/events");
|
||||
|
||||
void setupWebserver()
|
||||
{
|
||||
|
@ -10,6 +11,18 @@ void setupWebserver()
|
|||
return;
|
||||
}
|
||||
|
||||
events.onConnect([](AsyncEventSourceClient *client)
|
||||
{
|
||||
if (client->lastId())
|
||||
{
|
||||
Serial.printf("Client reconnected! Last message ID that it gat is: %u\n", client->lastId());
|
||||
}
|
||||
// send event with message "hello!", id current millis
|
||||
// and set reconnect delay to 1 second
|
||||
eventSourceLoop();
|
||||
});
|
||||
server.addHandler(&events);
|
||||
|
||||
server.serveStatic("/css", LittleFS, "/css/");
|
||||
server.serveStatic("/js", LittleFS, "/js/");
|
||||
server.serveStatic("/font", LittleFS, "/font/");
|
||||
|
@ -30,31 +43,38 @@ void setupWebserver()
|
|||
|
||||
server.on("/api/lights/off", HTTP_GET, onApiLightsOff);
|
||||
server.on("/api/lights/color", HTTP_GET, onApiLightsSetColor);
|
||||
server.on("^\\/api\\/lights\\/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", HTTP_GET, onApiLightsSetColor);
|
||||
|
||||
// server.on("^\\/api\\/lights\\/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", HTTP_GET, onApiLightsSetColor);
|
||||
|
||||
server.on("/api/restart", HTTP_GET, onApiRestart);
|
||||
|
||||
server.addRewrite(new OneParamRewrite("/api/lights/{color}", "/api/lights/color?c={color}"));
|
||||
server.addRewrite(new OneParamRewrite("/api/show/screen/{s}", "/api/show/screen?s={s}"));
|
||||
server.addRewrite(new OneParamRewrite("/api/show/text/{text}", "/api/show/text?t={text}"));
|
||||
server.addRewrite(new OneParamRewrite("/api/show/number/{number}", "/api/show/text?t={text}"));
|
||||
|
||||
server.onNotFound(onNotFound);
|
||||
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||
|
||||
server.begin();
|
||||
if (!MDNS.begin(getMyHostname()))
|
||||
{
|
||||
Serial.println(F("Error setting up MDNS responder!"));
|
||||
while (1)
|
||||
{
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Api
|
||||
* @Path("/api/status")
|
||||
*/
|
||||
void onApiStatus(AsyncWebServerRequest *request)
|
||||
StaticJsonDocument<768> getStatusObject()
|
||||
{
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
StaticJsonDocument<512> root;
|
||||
StaticJsonDocument<768> root;
|
||||
|
||||
root["currentScreen"] = getCurrentScreen();
|
||||
root["numScreens"] = NUM_SCREENS;
|
||||
root["timerRunning"] = isTimerActive();;
|
||||
root["timerRunning"] = isTimerActive();
|
||||
root["espUptime"] = esp_timer_get_time() / 1000000;
|
||||
root["currentPrice"] = getPrice();
|
||||
root["currentBlockHeight"] = getBlockHeight();
|
||||
|
@ -67,6 +87,37 @@ void onApiStatus(AsyncWebServerRequest *request)
|
|||
conStatus["price"] = isPriceNotifyConnected();
|
||||
conStatus["blocks"] = isBlockNotifyConnected();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void eventSourceLoop()
|
||||
{
|
||||
if (!events.count()) return;
|
||||
StaticJsonDocument<768> root = getStatusObject();
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
String epdContent[NUM_SCREENS];
|
||||
std::array<String, NUM_SCREENS> retEpdContent = getCurrentEpdContent();
|
||||
std::copy(std::begin(retEpdContent), std::end(retEpdContent), epdContent);
|
||||
|
||||
copyArray(epdContent, data);
|
||||
|
||||
size_t bufSize = measureJson(root);
|
||||
char buffer[bufSize];
|
||||
String bufString;
|
||||
serializeJson(root, bufString);
|
||||
|
||||
events.send(bufString.c_str(), "status");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Api
|
||||
* @Path("/api/status")
|
||||
*/
|
||||
void onApiStatus(AsyncWebServerRequest *request)
|
||||
{
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
|
||||
StaticJsonDocument<768> root = getStatusObject();
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonArray rendered = root.createNestedArray("rendered");
|
||||
String epdContent[NUM_SCREENS];
|
||||
|
@ -107,7 +158,6 @@ void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
|||
request->send(200);
|
||||
}
|
||||
|
||||
|
||||
void onApiShowScreen(AsyncWebServerRequest *request)
|
||||
{
|
||||
if (request->hasParam("s"))
|
||||
|
@ -128,13 +178,14 @@ void onApiShowText(AsyncWebServerRequest *request)
|
|||
t.toUpperCase(); // This is needed as long as lowercase letters are glitchy
|
||||
|
||||
std::array<String, NUM_SCREENS> textEpdContent;
|
||||
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
||||
{
|
||||
textEpdContent[i] = t[i];
|
||||
}
|
||||
|
||||
setEpdContent(textEpdContent);
|
||||
}
|
||||
//setCurrentScreen(SCREEN_CUSTOM);
|
||||
// setCurrentScreen(SCREEN_CUSTOM);
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
|
@ -156,7 +207,8 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
root["fgColor"] = getFgColor();
|
||||
root["bgColor"] = getBgColor();
|
||||
root["timerSeconds"] = getTimerSeconds();
|
||||
root["timerRunning"] = isTimerActive();;
|
||||
root["timerRunning"] = isTimerActive();
|
||||
root["minSecPriceUpd"] = preferences.getUInt("minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
||||
root["fullRefreshMin"] = preferences.getUInt("fullRefreshMin", 30);
|
||||
root["wpTimeout"] = preferences.getUInt("wpTimeout", 600);
|
||||
root["tzOffset"] = preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS) / 60;
|
||||
|
@ -166,7 +218,6 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
|||
root["rpcHost"] = preferences.getString("rpcHost", BITCOIND_HOST);
|
||||
root["mempoolInstance"] = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||
|
||||
root["epdColors"] = 2;
|
||||
root["ledFlashOnUpdate"] = preferences.getBool("ledFlashOnUpd", false);
|
||||
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
||||
|
||||
|
@ -312,6 +363,16 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
|||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (request->hasParam("minSecPriceUpd", true))
|
||||
{
|
||||
AsyncWebParameter *p = request->getParam("minSecPriceUpd", true);
|
||||
int minSecPriceUpd = p->value().toInt() * 60;
|
||||
preferences.putInt("minSecPriceUpd", minSecPriceUpd);
|
||||
Serial.print("Setting minSecPriceUpd ");
|
||||
Serial.println(minSecPriceUpd);
|
||||
settingsChanged = true;
|
||||
}
|
||||
|
||||
if (request->hasParam("timePerScreen", true))
|
||||
{
|
||||
AsyncWebParameter *p = request->getParam("timePerScreen", true);
|
||||
|
@ -381,14 +442,16 @@ void onApiLightsOff(AsyncWebServerRequest *request)
|
|||
|
||||
void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||
{
|
||||
String rgbColor = request->pathArg(0);
|
||||
uint r, g, b;
|
||||
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||
setLights(r, g, b);
|
||||
request->send(200, "text/plain", rgbColor);
|
||||
if (request->hasParam("c"))
|
||||
{
|
||||
String rgbColor = request->getParam("c")->value();
|
||||
uint r, g, b;
|
||||
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||
setLights(r, g, b);
|
||||
request->send(200, "text/plain", rgbColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void onIndex(AsyncWebServerRequest *request) { request->send(LittleFS, "/index.html", String(), false); }
|
||||
|
||||
void onNotFound(AsyncWebServerRequest *request)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "ESPAsyncWebServer.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <LittleFS.h>
|
||||
#include <ESPmDNS.h>
|
||||
|
||||
#include "lib/block_notify.hpp"
|
||||
#include "lib/price_notify.hpp"
|
||||
|
@ -32,4 +33,7 @@ void onApiLightsSetColor(AsyncWebServerRequest *request);
|
|||
void onApiRestart(AsyncWebServerRequest *request);
|
||||
|
||||
void onIndex(AsyncWebServerRequest *request);
|
||||
void onNotFound(AsyncWebServerRequest *request);
|
||||
void onNotFound(AsyncWebServerRequest *request);
|
||||
|
||||
StaticJsonDocument<768> getStatusObject();
|
||||
void eventSourceLoop();
|
|
@ -10,6 +10,7 @@ extern "C" void app_main()
|
|||
|
||||
while (true)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
eventSourceLoop();
|
||||
vTaskDelay(pdMS_TO_TICKS(2500));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue