Add missing settings, webUI as submodule
This commit is contained in:
parent
6c3796c776
commit
585b50d0ba
12 changed files with 209 additions and 45 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "data"]
|
||||||
|
path = data
|
||||||
|
url = https://github.com/btclock/oc-webui.git
|
1
data
Submodule
1
data
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 9df3329847f3939dc1242136e19746613fb83c4b
|
|
@ -9,7 +9,7 @@
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
data_dir = data/build
|
data_dir = data/build_gz
|
||||||
default_envs = lolin_s2_mini_213epd, lolin_s2_mini_29epd, lolin_s3_mini_213epd, lolin_s3_mini_29epd
|
default_envs = lolin_s2_mini_213epd, lolin_s2_mini_29epd, lolin_s3_mini_213epd, lolin_s3_mini_29epd
|
||||||
|
|
||||||
[btclock_base]
|
[btclock_base]
|
||||||
|
@ -19,6 +19,7 @@ monitor_speed = 115200
|
||||||
monitor_filters = esp32_exception_decoder, colorize
|
monitor_filters = esp32_exception_decoder, colorize
|
||||||
board_build.filesystem = littlefs
|
board_build.filesystem = littlefs
|
||||||
board_build.partitions = partition.csv
|
board_build.partitions = partition.csv
|
||||||
|
extra_scripts = post:scripts/extra_script.py
|
||||||
build_flags =
|
build_flags =
|
||||||
!python scripts/git_rev.py
|
!python scripts/git_rev.py
|
||||||
-DLAST_BUILD_TIME=$UNIX_TIME
|
-DLAST_BUILD_TIME=$UNIX_TIME
|
||||||
|
|
38
scripts/extra_script.py
Normal file
38
scripts/extra_script.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
Import("env")
|
||||||
|
import os
|
||||||
|
import gzip
|
||||||
|
from shutil import copyfileobj, rmtree
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
def gzip_file(input_file, output_file):
|
||||||
|
with open(input_file, 'rb') as f_in:
|
||||||
|
with gzip.open(output_file, 'wb') as f_out:
|
||||||
|
copyfileobj(f_in, f_out)
|
||||||
|
|
||||||
|
def process_directory(input_dir, output_dir):
|
||||||
|
if os.path.exists(output_dir):
|
||||||
|
rmtree(output_dir)
|
||||||
|
for root, dirs, files in os.walk(input_dir):
|
||||||
|
relative_path = os.path.relpath(root, input_dir)
|
||||||
|
output_root = os.path.join(output_dir, relative_path)
|
||||||
|
|
||||||
|
Path(output_root).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
for file in files:
|
||||||
|
# if file.endswith(('.html', '.css', '.js')):
|
||||||
|
input_file_path = os.path.join(root, file)
|
||||||
|
output_file_path = os.path.join(output_root, file + '.gz')
|
||||||
|
gzip_file(input_file_path, output_file_path)
|
||||||
|
print(f'Compressed: {input_file_path} -> {output_file_path}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Build web interface before building FS
|
||||||
|
def before_buildfs(source, target, env):
|
||||||
|
env.Execute("cd data && yarn && yarn postinstall && yarn build")
|
||||||
|
input_directory = 'data/dist'
|
||||||
|
output_directory = 'data/build_gz'
|
||||||
|
process_directory(input_directory, output_directory)
|
||||||
|
|
||||||
|
os.environ["PUBLIC_BASE_URL"] = ""
|
||||||
|
env.AddPreAction("$BUILD_DIR/littlefs.bin", before_buildfs)
|
|
@ -3,7 +3,7 @@
|
||||||
Preferences preferences;
|
Preferences preferences;
|
||||||
|
|
||||||
const char *ntpServer = "pool.ntp.org";
|
const char *ntpServer = "pool.ntp.org";
|
||||||
const long gmtOffset_sec = 0;
|
// const long gmtOffset_sec = 0;
|
||||||
const int daylightOffset_sec = 3600;
|
const int daylightOffset_sec = 3600;
|
||||||
TaskHandle_t OTAHandle = NULL;
|
TaskHandle_t OTAHandle = NULL;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ bool isUpdating = false;
|
||||||
|
|
||||||
void setupTime()
|
void setupTime()
|
||||||
{
|
{
|
||||||
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
|
configTime(preferences.getInt(SETTING_TIME_OFFSET_MIN), daylightOffset_sec, ntpServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPreferences()
|
void setupPreferences()
|
||||||
|
@ -48,10 +48,44 @@ void setupPreferences()
|
||||||
{
|
{
|
||||||
preferences.putString(SETTING_MEMPOOL_INSTANCE, "https://mempool.space");
|
preferences.putString(SETTING_MEMPOOL_INSTANCE, "https://mempool.space");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!preferences.isKey(SETTING_TIME_FORMAT))
|
||||||
|
{
|
||||||
|
preferences.putString(SETTING_TIME_FORMAT, "%H:%M:%S");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preferences.isKey(SETTING_DATE_FORMAT))
|
||||||
|
{
|
||||||
|
preferences.putString(SETTING_DATE_FORMAT, "%d-%m-%Y");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preferences.isKey(SETTING_DECIMAL_SEPARATOR))
|
||||||
|
{
|
||||||
|
preferences.putChar(SETTING_DECIMAL_SEPARATOR, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preferences.isKey(SETTING_POWER_SAVE_MODE))
|
||||||
|
{
|
||||||
|
preferences.putBool(SETTING_POWER_SAVE_MODE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preferences.isKey(SETTING_TIME_OFFSET_MIN))
|
||||||
|
{
|
||||||
|
preferences.putInt(SETTING_TIME_OFFSET_MIN, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWifi()
|
void setupWifi()
|
||||||
{
|
{
|
||||||
|
uint8_t mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
unsigned long seed = 0;
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
seed += (unsigned long)mac[i] << ((i & 1) * 8);
|
||||||
|
}
|
||||||
|
randomSeed(seed);
|
||||||
|
|
||||||
// WiFi.begin(, ");
|
// WiFi.begin(, ");
|
||||||
WiFi.setAutoConnect(true);
|
WiFi.setAutoConnect(true);
|
||||||
WiFi.setAutoReconnect(true);
|
WiFi.setAutoReconnect(true);
|
||||||
|
@ -75,15 +109,10 @@ void setupWifi()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte mac[6];
|
|
||||||
WiFi.macAddress(mac);
|
|
||||||
String softAP_SSID =
|
String softAP_SSID =
|
||||||
String("OrangeBTClock");
|
String("OrangeBTClock");
|
||||||
WiFi.setHostname(softAP_SSID.c_str());
|
WiFi.setHostname(softAP_SSID.c_str());
|
||||||
String softAP_password =
|
String softAP_password = getAPPassword();
|
||||||
base64::encode(String(mac[2], 16) + String(mac[4], 16) +
|
|
||||||
String(mac[5], 16) + String(mac[1], 16))
|
|
||||||
.substring(2, 10);
|
|
||||||
|
|
||||||
// wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", 600));
|
// wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", 600));
|
||||||
wm.setWiFiAutoReconnect(false);
|
wm.setWiFiAutoReconnect(false);
|
||||||
|
@ -214,31 +243,36 @@ void setupOTA()
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
|
|
||||||
xTaskCreatePinnedToCore(
|
xTaskCreatePinnedToCore(
|
||||||
OTAUpdateTask, // Task function
|
OTAUpdateTask, // Task function
|
||||||
"OTAUpdateTask", // Task name
|
"OTAUpdateTask", // Task name
|
||||||
4096, // Stack size
|
4096, // Stack size
|
||||||
NULL, // Task parameters
|
NULL, // Task parameters
|
||||||
1, // Priority (higher value means higher priority)
|
1, // Priority (higher value means higher priority)
|
||||||
&OTAHandle, // Task handle
|
&OTAHandle, // Task handle
|
||||||
0 // Core to run the task (0 or 1)
|
0 // Core to run the task (0 or 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OTAUpdateTask(void *pvParameters)
|
||||||
void OTAUpdateTask(void *pvParameters) {
|
{
|
||||||
for (;;) {
|
for (;;)
|
||||||
ArduinoOTA.handle(); // Handle OTA updates
|
{
|
||||||
|
ArduinoOTA.handle(); // Handle OTA updates
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay to avoid high CPU usage
|
vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay to avoid high CPU usage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char getCurrencyIcon() {
|
char getCurrencyIcon()
|
||||||
|
{
|
||||||
char ret;
|
char ret;
|
||||||
const char* currency = preferences.getString(SETTING_CURRENCY).c_str();
|
const char *currency = preferences.getString(SETTING_CURRENCY).c_str();
|
||||||
if (strcmp(currency, CURRENCY_USD) == 0) {
|
if (strcmp(currency, CURRENCY_USD) == 0)
|
||||||
ret = ICON_DOLLAR;
|
{
|
||||||
} else if(strcmp(currency, CURRENCY_EUR) == 0) {
|
ret = ICON_DOLLAR;
|
||||||
ret = ICON_EURO;
|
}
|
||||||
|
else if (strcmp(currency, CURRENCY_EUR) == 0)
|
||||||
|
{
|
||||||
|
ret = ICON_EURO;
|
||||||
}
|
}
|
||||||
// break;
|
// break;
|
||||||
// case CURRENCY_GBP:
|
// case CURRENCY_GBP:
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -59,6 +59,7 @@ void loop()
|
||||||
{
|
{
|
||||||
if (isUpdating)
|
if (isUpdating)
|
||||||
{
|
{
|
||||||
|
delay(1000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,22 +136,22 @@ void loop()
|
||||||
{
|
{
|
||||||
icon = getCurrencyIcon();
|
icon = getCurrencyIcon();
|
||||||
int64_t marketCap = static_cast<std::int64_t>(getSupplyAtBlock(getBlock()) * double(getPrice()));
|
int64_t marketCap = static_cast<std::int64_t>(getSupplyAtBlock(getBlock()) * double(getPrice()));
|
||||||
rowContent = String(formatNumberWithSuffix(marketCap, 4));
|
rowContent = String(formatNumberWithSuffix(marketCap, 8));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LINE_TIME:
|
case LINE_TIME:
|
||||||
{
|
{
|
||||||
icon = ICON_GLOBE;
|
icon = ICON_GLOBE;
|
||||||
char dateString[10];
|
char dateString[16];
|
||||||
strftime(dateString, 10, "%H:%M:%S", &timeinfo);
|
strftime(dateString, sizeof(dateString), preferences.getString(SETTING_TIME_FORMAT).c_str(), &timeinfo);
|
||||||
rowContent = dateString;
|
rowContent = dateString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LINE_DATE:
|
case LINE_DATE:
|
||||||
{
|
{
|
||||||
icon = ICON_GLOBE;
|
icon = ICON_GLOBE;
|
||||||
char dateString[10];
|
char dateString[16];
|
||||||
strftime(dateString, 10, "%x", &timeinfo);
|
strftime(dateString, sizeof(dateString), preferences.getString(SETTING_DATE_FORMAT).c_str(), &timeinfo);
|
||||||
rowContent = dateString;
|
rowContent = dateString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,2 @@
|
||||||
#include "shared.hpp"
|
#include "shared.hpp"
|
||||||
|
|
||||||
String getMyHostname()
|
|
||||||
{
|
|
||||||
uint8_t mac[6];
|
|
||||||
// WiFi.macAddress(mac);
|
|
||||||
esp_efuse_mac_get_default(mac);
|
|
||||||
char hostname[15];
|
|
||||||
String hostnamePrefix = preferences.getString(SETTING_HOSTNAME_PREFIX);
|
|
||||||
snprintf(hostname, sizeof(hostname), "%s-%02x%02x%02x", hostnamePrefix,
|
|
||||||
mac[3], mac[4], mac[5]);
|
|
||||||
return hostname;
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <GxEPD2.h>
|
#include <GxEPD2.h>
|
||||||
#include <GxEPD2_BW.h>
|
#include <GxEPD2_BW.h>
|
||||||
|
#include "utils.hpp"
|
||||||
#include "fonts/fonts.hpp"
|
#include "fonts/fonts.hpp"
|
||||||
|
|
||||||
#ifdef VERSION_EPD_2_13
|
#ifdef VERSION_EPD_2_13
|
||||||
|
@ -62,6 +63,12 @@
|
||||||
#define SETTING_CURRENCY "currency"
|
#define SETTING_CURRENCY "currency"
|
||||||
#define SETTING_HOSTNAME_PREFIX "hostnamePrefix"
|
#define SETTING_HOSTNAME_PREFIX "hostnamePrefix"
|
||||||
#define SETTING_MEMPOOL_INSTANCE "mempoolInstance"
|
#define SETTING_MEMPOOL_INSTANCE "mempoolInstance"
|
||||||
|
#define SETTING_POWER_SAVE_MODE "powerSaveMode"
|
||||||
|
#define SETTING_TIME_OFFSET_MIN "timeOffsetMin"
|
||||||
|
#define SETTING_DECIMAL_SEPARATOR "decSeparator"
|
||||||
|
#define SETTING_TIME_FORMAT "timeFormat"
|
||||||
|
#define SETTING_DATE_FORMAT "dateFormat"
|
||||||
|
|
||||||
|
|
||||||
const int LINE_BLOCKHEIGHT = 0;
|
const int LINE_BLOCKHEIGHT = 0;
|
||||||
const int LINE_MEMPOOL_FEES = 1;
|
const int LINE_MEMPOOL_FEES = 1;
|
||||||
|
@ -94,4 +101,3 @@ extern char currentIcon1;
|
||||||
extern char currentIcon2;
|
extern char currentIcon2;
|
||||||
extern char currentIcon3;
|
extern char currentIcon3;
|
||||||
|
|
||||||
String getMyHostname();
|
|
||||||
|
|
32
src/utils.cpp
Normal file
32
src/utils.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
String getAPPassword()
|
||||||
|
{
|
||||||
|
byte mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
const char charset[] = "abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789";
|
||||||
|
char password[9]; // 8 characters + null terminator
|
||||||
|
snprintf(password, sizeof(password), "%c%c%c%c%c%c%c%c",
|
||||||
|
charset[mac[0] % (sizeof(charset) - 1)],
|
||||||
|
charset[mac[1] % (sizeof(charset) - 1)],
|
||||||
|
charset[mac[2] % (sizeof(charset) - 1)],
|
||||||
|
charset[mac[3] % (sizeof(charset) - 1)],
|
||||||
|
charset[mac[4] % (sizeof(charset) - 1)],
|
||||||
|
charset[mac[5] % (sizeof(charset) - 1)],
|
||||||
|
charset[(mac[0] + mac[1] + mac[2] + mac[3] + mac[4] + mac[5]) % (sizeof(charset) - 1)],
|
||||||
|
charset[(mac[0] * mac[1] * mac[2] * mac[3] * mac[4] * mac[5]) % (sizeof(charset) - 1)]);
|
||||||
|
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMyHostname()
|
||||||
|
{
|
||||||
|
uint8_t mac[6];
|
||||||
|
// WiFi.macAddress(mac);
|
||||||
|
esp_efuse_mac_get_default(mac);
|
||||||
|
char hostname[15];
|
||||||
|
String hostnamePrefix = preferences.getString(SETTING_HOSTNAME_PREFIX);
|
||||||
|
snprintf(hostname, sizeof(hostname), "%s-%02x%02x%02x", hostnamePrefix,
|
||||||
|
mac[3], mac[4], mac[5]);
|
||||||
|
return hostname;
|
||||||
|
}
|
27
src/utils.hpp
Normal file
27
src/utils.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.hpp>
|
||||||
|
#include "shared.hpp"
|
||||||
|
|
||||||
|
namespace ArduinoJson {
|
||||||
|
template <>
|
||||||
|
struct Converter<char> {
|
||||||
|
static void toJson(char c, JsonVariant var) {
|
||||||
|
var.set(static_cast<signed char>(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
static char fromJson(JsonVariantConst src) {
|
||||||
|
return static_cast<char>(src.as<signed char>());
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkJson(JsonVariantConst src) {
|
||||||
|
return src.is<signed char>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String getAPPassword();
|
||||||
|
String getMyHostname();
|
|
@ -3,8 +3,10 @@
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
const String uintSettings[] = {SETTING_ROW1_CONTENT, SETTING_ROW2_CONTENT, SETTING_ROW3_CONTENT};
|
const String uintSettings[] = {SETTING_ROW1_CONTENT, SETTING_ROW2_CONTENT, SETTING_ROW3_CONTENT};
|
||||||
const String stringSettings[] = {SETTING_CURRENCY,SETTING_MEMPOOL_INSTANCE};
|
const String intSettings[] = {SETTING_TIME_OFFSET_MIN};
|
||||||
const String boolSettings[] = {};
|
const String stringSettings[] = {SETTING_CURRENCY, SETTING_MEMPOOL_INSTANCE, SETTING_TIME_FORMAT, SETTING_DATE_FORMAT};
|
||||||
|
const String charSettings[] = {SETTING_DECIMAL_SEPARATOR};
|
||||||
|
const String boolSettings[] = {SETTING_POWER_SAVE_MODE};
|
||||||
|
|
||||||
void setupWebserver()
|
void setupWebserver()
|
||||||
{
|
{
|
||||||
|
@ -68,11 +70,21 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root[setting] = preferences.getUInt(setting.c_str());
|
root[setting] = preferences.getUInt(setting.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String setting : intSettings)
|
||||||
|
{
|
||||||
|
root[setting] = preferences.getInt(setting.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
for (String setting : stringSettings)
|
for (String setting : stringSettings)
|
||||||
{
|
{
|
||||||
root[setting] = preferences.getString(setting.c_str());
|
root[setting] = preferences.getString(setting.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String setting : charSettings)
|
||||||
|
{
|
||||||
|
root[setting] = preferences.getChar(setting.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
for (String setting : boolSettings)
|
for (String setting : boolSettings)
|
||||||
{
|
{
|
||||||
root[setting] = preferences.getBool(setting.c_str());
|
root[setting] = preferences.getBool(setting.c_str());
|
||||||
|
@ -110,6 +122,16 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String setting : intSettings)
|
||||||
|
{
|
||||||
|
if (settings.containsKey(setting))
|
||||||
|
{
|
||||||
|
preferences.putInt(setting.c_str(), settings[setting].as<int>());
|
||||||
|
Serial.printf("Setting %s to %d\r\n", setting.c_str(),
|
||||||
|
settings[setting].as<uint>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (String setting : stringSettings)
|
for (String setting : stringSettings)
|
||||||
{
|
{
|
||||||
if (settings.containsKey(setting))
|
if (settings.containsKey(setting))
|
||||||
|
@ -120,6 +142,16 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String setting : charSettings)
|
||||||
|
{
|
||||||
|
if (settings.containsKey(setting))
|
||||||
|
{
|
||||||
|
preferences.putChar(setting.c_str(), settings[setting].as<char>());
|
||||||
|
Serial.printf("Setting %s to %s\r\n", setting.c_str(),
|
||||||
|
settings[setting].as<String>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (String setting : boolSettings)
|
for (String setting : boolSettings)
|
||||||
{
|
{
|
||||||
if (settings.containsKey(setting))
|
if (settings.containsKey(setting))
|
||||||
|
|
Loading…
Reference in a new issue