Made more options configurable in the web interface
This commit is contained in:
parent
fb1cd73acf
commit
81885e3f15
6 changed files with 111 additions and 20 deletions
|
@ -109,12 +109,22 @@
|
||||||
<label for="timePerScreen" class="col-sm-6 col-form-label">Time per screen</label>
|
<label for="timePerScreen" class="col-sm-6 col-form-label">Time per screen</label>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<input type="text" name="timePerScreen" id="timePerScreen">
|
<input type="text" name="timePerScreen" id="timePerScreen" class="form-control">
|
||||||
<span class="input-group-text" id="basic-addon2">minutes</span>
|
<span class="input-group-text">minutes</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class=" col-sm-6">
|
<div class=" col-sm-6">
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
|
@ -123,6 +133,39 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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="useBitcoinNode" name="useBitcoinNode" value="1">
|
||||||
|
<label class="form-check-label" for="useBitcoinNode">Use local node</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label for="rpcHost" class="col-sm-6 col-form-label">Node IP/hostname</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="rpcHost" id="rpcHost" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label for="rpcPort" class="col-sm-6 col-form-label">RPC port</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="number" name="rpcPort" id="rpcPort" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label for="rpcUser" class="col-sm-6 col-form-label">RPC username</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="text" name="rpcUser" id="rpcUser" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label for="rpcPass" class="col-sm-6 col-form-label">RPC password</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="password" name="rpcPass" id="rpcPass" class="form-control">
|
||||||
|
<div class="form-text">For security, password is not shown after saving.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<script id="screens-template" type="text/x-handlebars-template">
|
<script id="screens-template" type="text/x-handlebars-template">
|
||||||
{{#each screens }}
|
{{#each screens }}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
//import "./handlebars.js";
|
|
||||||
import './helpers.js';
|
import './helpers.js';
|
||||||
|
|
||||||
var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown"];
|
var screens = ["Block Height", "Moscow Time", "Ticker", "Time", "Halving countdown"];
|
||||||
|
|
||||||
getBcStatus = () => {
|
getBcStatus = () => {
|
||||||
fetch('http://btclock3.local/api/status', {
|
fetch('/api/status', {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
|
@ -22,7 +21,7 @@ getBcStatus = () => {
|
||||||
interval = setInterval(getBcStatus, 2500);
|
interval = setInterval(getBcStatus, 2500);
|
||||||
getBcStatus();
|
getBcStatus();
|
||||||
|
|
||||||
fetch('http://btclock3.local/api/settings', {
|
fetch('/api/settings', {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
|
@ -42,6 +41,15 @@ fetch('http://btclock3.local/api/settings', {
|
||||||
if (jsonData.ledFlashOnUpdate)
|
if (jsonData.ledFlashOnUpdate)
|
||||||
document.getElementById('ledFlashOnUpdate').checked = true;
|
document.getElementById('ledFlashOnUpdate').checked = true;
|
||||||
|
|
||||||
|
if (jsonData.useBitcoinNode)
|
||||||
|
document.getElementById('useBitcoinNode').checked = true;
|
||||||
|
|
||||||
|
let nodeFields = ["rpcHost", "rpcPort", "rpcUser", "tzOffset"];
|
||||||
|
|
||||||
|
for (let n of nodeFields) {
|
||||||
|
document.getElementById(n).value = jsonData[n];
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('timePerScreen').value = jsonData.timerSeconds / 60;
|
document.getElementById('timePerScreen').value = jsonData.timerSeconds / 60;
|
||||||
|
|
||||||
var source = document.getElementById("screens-template").innerHTML;
|
var source = document.getElementById("screens-template").innerHTML;
|
||||||
|
@ -54,11 +62,12 @@ fetch('http://btclock3.local/api/settings', {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var settingsForm = document.querySelector('#settingsForm');
|
var settingsForm = document.querySelector('#settingsForm');
|
||||||
settingsForm.onsubmit = (event) => {
|
settingsForm.onsubmit = (event) => {
|
||||||
var formData = new FormData(settingsForm);
|
var formData = new FormData(settingsForm);
|
||||||
|
|
||||||
fetch("http://btclock3.local/api/settings",
|
fetch("/api/settings",
|
||||||
{
|
{
|
||||||
body: formData,
|
body: formData,
|
||||||
method: "post"
|
method: "post"
|
||||||
|
@ -88,6 +97,14 @@ turnOffLedsBtn.onclick = (event) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let tzOffsetBtn = document.getElementById('getTzOffsetBtn');
|
||||||
|
|
||||||
|
if (tzOffsetBtn)
|
||||||
|
tzOffsetBtn.onclick = (event) => {
|
||||||
|
document.getElementById("tzOffset").value = new Date(new Date().getFullYear(), 0, 1).getTimezoneOffset()*-1;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
var textForm = document.querySelector('#customTextForm');
|
var textForm = document.querySelector('#customTextForm');
|
||||||
textForm.onsubmit = (event) => {
|
textForm.onsubmit = (event) => {
|
||||||
var formData = new FormData(textForm);
|
var formData = new FormData(textForm);
|
||||||
|
|
|
@ -76,12 +76,12 @@ void setupComponents()
|
||||||
|
|
||||||
void synchronizeTime()
|
void synchronizeTime()
|
||||||
{
|
{
|
||||||
configTime(3600, 0, NTP_SERVER);
|
configTime(preferences.getUInt("gmtOffset", TIME_OFFSET_SECONDS), 0, NTP_SERVER);
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
|
|
||||||
while (!getLocalTime(&timeinfo))
|
while (!getLocalTime(&timeinfo))
|
||||||
{
|
{
|
||||||
configTime(3600, 0, NTP_SERVER);
|
configTime(preferences.getUInt("gmtOffset", TIME_OFFSET_SECONDS), 0, NTP_SERVER);
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.println("Retry set time");
|
Serial.println("Retry set time");
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,6 @@ void setupPreferences()
|
||||||
bgColor = preferences.getUInt("bgColor", DEFAULT_BG_COLOR);
|
bgColor = preferences.getUInt("bgColor", DEFAULT_BG_COLOR);
|
||||||
preferences.getBool("ledFlashOnUpd", false);
|
preferences.getBool("ledFlashOnUpd", false);
|
||||||
|
|
||||||
// screenNameMap = {{SCREEN_BLOCK_HEIGHT, "Block Height"};
|
|
||||||
|
|
||||||
screenNameMap = {{SCREEN_BLOCK_HEIGHT, "Block Height"},
|
screenNameMap = {{SCREEN_BLOCK_HEIGHT, "Block Height"},
|
||||||
{SCREEN_MSCW_TIME, "Sats per dollar"},
|
{SCREEN_MSCW_TIME, "Sats per dollar"},
|
||||||
|
|
|
@ -142,6 +142,11 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root["bgColor"] = getBgColor();
|
root["bgColor"] = getBgColor();
|
||||||
root["timerSeconds"] = timerSeconds;
|
root["timerSeconds"] = timerSeconds;
|
||||||
root["timerRunning"] = timerRunning;
|
root["timerRunning"] = timerRunning;
|
||||||
|
root["tzOffset"] = preferences.getUInt("gmtOffset", TIME_OFFSET_SECONDS) / 60;
|
||||||
|
root["useBitcoinNode"] = preferences.getBool("useNode", false);
|
||||||
|
root["rpcPort"] = preferences.getUInt("rpcPort", BITCOIND_PORT);
|
||||||
|
root["rpcUser"] = preferences.getString("rpcUser", BITCOIND_RPC_USER);
|
||||||
|
root["rpcHost"] = preferences.getString("rpcHost", BITCOIND_HOST);
|
||||||
#ifdef IS_BW
|
#ifdef IS_BW
|
||||||
root["epdColors"] = 2;
|
root["epdColors"] = 2;
|
||||||
#else
|
#else
|
||||||
|
@ -219,6 +224,14 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
preferences.putBool(prefKey.c_str(), visible);
|
preferences.putBool(prefKey.c_str(), visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("tzOffset", true))
|
||||||
|
{
|
||||||
|
AsyncWebParameter *p = request->getParam("tzOffset", true);
|
||||||
|
int tzOffsetSeconds = p->value().toInt() * 60;
|
||||||
|
preferences.putUInt("tzOffset", tzOffsetSeconds);
|
||||||
|
settingsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (request->hasParam("timePerScreen", true))
|
if (request->hasParam("timePerScreen", true))
|
||||||
{
|
{
|
||||||
AsyncWebParameter *p = request->getParam("timePerScreen", true);
|
AsyncWebParameter *p = request->getParam("timePerScreen", true);
|
||||||
|
@ -227,6 +240,25 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->hasParam("useBitcoinNode", true))
|
||||||
|
{
|
||||||
|
AsyncWebParameter *p = request->getParam("useBitcoinNode", true);
|
||||||
|
bool useBitcoinNode = p->value().toInt();
|
||||||
|
preferences.putBool("useNode", useBitcoinNode);
|
||||||
|
settingsChanged = true;
|
||||||
|
|
||||||
|
String rpcVars[] = {"rpcHost", "rpcPort", "rpcUser", "rpcPass"};
|
||||||
|
|
||||||
|
for (String v : rpcVars)
|
||||||
|
{
|
||||||
|
if (request->hasParam(v, true))
|
||||||
|
{
|
||||||
|
AsyncWebParameter *pv = request->getParam(v, true);
|
||||||
|
preferences.putString(v.c_str(), pv->value().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
if (settingsChanged)
|
if (settingsChanged)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@ void checkBitcoinBlock(void *pvParameters)
|
||||||
int blockHeight = preferences.getUInt("blockHeight", currentBlockHeight);
|
int blockHeight = preferences.getUInt("blockHeight", currentBlockHeight);
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
http.setReuse(true);
|
http.setReuse(true);
|
||||||
useBitcoind = wifiClientInsecure.connect(BITCOIND_HOST, BITCOIND_PORT);
|
useBitcoind = wifiClientInsecure.connect(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||||
if (useBitcoind)
|
if (useBitcoind)
|
||||||
Serial.println("bitcoind node is reachable, using this for blocks.");
|
Serial.println("bitcoind node is reachable, using this for blocks.");
|
||||||
else
|
else
|
||||||
|
@ -32,10 +32,10 @@ void checkBitcoinBlock(void *pvParameters)
|
||||||
{
|
{
|
||||||
StaticJsonDocument<200> jsonDoc;
|
StaticJsonDocument<200> jsonDoc;
|
||||||
|
|
||||||
http.begin(BITCOIND_HOST, BITCOIND_PORT);
|
http.begin(preferences.getString("rpcHost", BITCOIND_HOST).c_str(), preferences.getUInt("rpcPort", BITCOIND_PORT));
|
||||||
http.addHeader("Content-Type", "application/json");
|
http.addHeader("Content-Type", "application/json");
|
||||||
String payload = "{\"jsonrpc\":\"1.0\",\"id\":\"current_block_height\",\"method\":\"getblockcount\",\"params\":[]}";
|
String payload = "{\"jsonrpc\":\"1.0\",\"id\":\"current_block_height\",\"method\":\"getblockcount\",\"params\":[]}";
|
||||||
String auth = String(BITCOIND_RPC_USER) + ":" + String(BITCOIND_RPC_PASS);
|
String auth = preferences.getString("rpcUser", BITCOIND_RPC_USER) + ":" + preferences.getString("rpcPass", BITCOIND_RPC_PASS);
|
||||||
String authEncoded = base64::encode(auth);
|
String authEncoded = base64::encode(auth);
|
||||||
http.addHeader("Authorization", "Basic " + authEncoded);
|
http.addHeader("Authorization", "Basic " + authEncoded);
|
||||||
|
|
||||||
|
|
|
@ -21,20 +21,21 @@ void taskGetPrice(void *pvParameters)
|
||||||
int httpCode = http.GET();
|
int httpCode = http.GET();
|
||||||
|
|
||||||
// Parse JSON response and extract average price
|
// Parse JSON response and extract average price
|
||||||
float price;
|
float usdPrice, eurPrice;
|
||||||
if (httpCode == 200)
|
if (httpCode == 200)
|
||||||
{
|
{
|
||||||
String payload = http.getString();
|
String payload = http.getString();
|
||||||
//Serial.println(payload);
|
|
||||||
StaticJsonDocument<768> doc;
|
StaticJsonDocument<768> doc;
|
||||||
deserializeJson(doc, payload);
|
deserializeJson(doc, payload);
|
||||||
JsonObject bpi = doc["bpi"];
|
JsonObject bpi = doc["bpi"];
|
||||||
price = bpi["USD"]["rate_float"];
|
usdPrice = bpi["USD"]["rate_float"];
|
||||||
|
eurPrice = bpi["EUR"]["rate_float"];
|
||||||
for(auto &callback : priceEventCallbacks) { // Loop through all the event callbacks and call them
|
for(auto &callback : priceEventCallbacks) { // Loop through all the event callbacks and call them
|
||||||
callback(price);
|
callback(usdPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
preferences.putFloat("btcPrice", price);
|
preferences.putFloat("btcPrice", usdPrice);
|
||||||
|
preferences.putFloat("btcPriceEur", eurPrice);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -42,7 +43,6 @@ void taskGetPrice(void *pvParameters)
|
||||||
Serial.println(httpCode);
|
Serial.println(httpCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect from Wi-Fi network and wait for 60 seconds
|
|
||||||
http.end();
|
http.end();
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(PRICE_WAIT_TIME));
|
vTaskDelay(pdMS_TO_TICKS(PRICE_WAIT_TIME));
|
||||||
|
|
Loading…
Reference in a new issue