WebUI: Add German translation, switch to own price source

This commit is contained in:
Djuri Baars 2024-05-08 23:54:17 +02:00
parent a2fa0a12a8
commit efaab00fb4
6 changed files with 117 additions and 48 deletions

2
data

@ -1 +1 @@
Subproject commit dcdf98964a42ccd83b2d2501bbed46a640bbc300
Subproject commit e47fc066b0608132c44a35f7041be80b263adcff

View file

@ -41,7 +41,8 @@ void setup()
if (mcp1.digitalRead(0) == LOW)
{
// Then loop forever to prevent anything else from writing to the screen
while (true) {
while (true)
{
delay(1000);
}
}
@ -84,7 +85,7 @@ void tryImprovSetup()
}
}
// if (!preferences.getBool("wifiConfigured", false))
// if (!preferences.getBool("wifiConfigured", false))
{
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
@ -130,13 +131,23 @@ void tryImprovSetup()
const String explainText = "*SSID: *\r\n" +
wifiManager->getConfigPortalSSID() +
"\r\n\r\n*Password:*\r\n" + softAP_password;
// Set the UNIX timestamp
time_t timestamp = LAST_BUILD_TIME; // Example timestamp: March 7, 2021 00:00:00 UTC
// Convert the timestamp to a struct tm in UTC
struct tm *timeinfo = gmtime(&timestamp);
// Format the date
char formattedDate[20];
strftime(formattedDate, sizeof(formattedDate), "%y-%m-%d\r\n%H:%M:%S", timeinfo);
std::array<String, NUM_SCREENS> epdContent = {
"Welcome!",
"Bienvenidos!",
"To setup\r\nscan QR or\r\nconnect\r\nmanually",
"Para\r\nconfigurar\r\nescanear QR\r\no conectar\r\nmanualmente",
explainText,
"*Hostname*:\r\n" + getMyHostname(),
"*Hostname*:\r\n" + getMyHostname() + "\r\n\r\n" + "*FW build date:*\r\n" + formattedDate,
qrText};
setEpdContent(epdContent); });
@ -311,6 +322,17 @@ void setupHardware()
Serial.println(F("Error loading WebUI"));
}
// if (!LittleFS.exists("/qr.txt"))
// {
// File f = LittleFS.open("/qr.txt", "w");
// if(f) {
// } else {
// Serial.println(F("Can't write QR to FS"));
// }
// }
setupLeds();
WiFi.setHostname(getMyHostname().c_str());
@ -665,17 +687,27 @@ String getMyHostname()
return hostname;
}
uint getLastTimeSync() {
uint getLastTimeSync()
{
return lastTimeSync;
}
#ifdef HAS_FRONTLIGHT
void setupFrontlight() {
flArray.begin();
void setupFrontlight()
{
if (!flArray.begin(PCA9685_MODE1_AUTOINCR, PCA9685_MODE2_INVERT))
{
Serial.println(F("FL driver error"));
return;
}
Serial.println(F("FL driver active"));
flArray.setFrequency(1000);
flArray.setOutputEnablePin(PCA_OE_PIN);
if (!preferences.isKey("flMaxBrightness")) {
flArray.setOutputEnable(true);
delay(1000);
flArray.setOutputEnable(false);
if (!preferences.isKey("flMaxBrightness"))
{
preferences.putUInt("flMaxBrightness", 4095);
}
// Initialize all LEDs to off

View file

@ -339,7 +339,7 @@ void frontlightFadeInAll() {
for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) {
flArray.setPWM(ledPin, 0, dutyCycle);
}
delay(flDelayTime);
vTaskDelay(pdMS_TO_TICKS(flDelayTime));
}
}
@ -348,21 +348,21 @@ void frontlightFadeOutAll() {
for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) {
flArray.setPWM(ledPin, 0, dutyCycle);
}
delay(flDelayTime);
vTaskDelay(pdMS_TO_TICKS(flDelayTime));
}
}
void frontlightFadeIn(uint num) {
for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) {
flArray.setPWM(num, 0, dutyCycle);
delay(flDelayTime);
vTaskDelay(pdMS_TO_TICKS(flDelayTime));
}
}
void frontlightFadeOut(uint num) {
for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) {
flArray.setPWM(num, 0, dutyCycle);
delay(flDelayTime);
vTaskDelay(pdMS_TO_TICKS(flDelayTime));
}
}
#endif

View file

@ -1,5 +1,6 @@
#include "price_notify.hpp"
const char *wsOwnServerPrice = "wss://ws.btclock.store/ws?assets=bitcoin";
const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
// const char* coinCapWsCert = R"(-----BEGIN CERTIFICATE-----
@ -35,17 +36,25 @@ const char *wsServerPrice = "wss://ws.coincap.io/prices?assets=bitcoin";
// WebsocketsClient client;
esp_websocket_client_handle_t clientPrice = NULL;
uint currentPrice = 30000;
esp_websocket_client_config_t config;
uint currentPrice = 50000;
unsigned long int lastPriceUpdate;
bool priceNotifyInit = false;
void setupPriceNotify() {
void setupPriceNotify()
{
// currentPrice = preferences.get("lastPrice", 30000);
esp_websocket_client_config_t config = {.uri = wsServerPrice,
// .task_stack = (7*1024),
// .cert_pem = coinCapWsCert,
.user_agent = USER_AGENT};
if (preferences.getBool("ownPriceSource", true))
{
config = {.uri = wsOwnServerPrice,
.user_agent = USER_AGENT};
}
else
{
config = {.uri = wsServerPrice,
.user_agent = USER_AGENT};
}
clientPrice = esp_websocket_client_init(&config);
esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY,
@ -54,40 +63,46 @@ void setupPriceNotify() {
}
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
int32_t event_id, void *event_data) {
int32_t event_id, void *event_data)
{
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
switch (event_id) {
case WEBSOCKET_EVENT_CONNECTED:
Serial.println(F("Connected to CoinCap.io WebSocket"));
priceNotifyInit = true;
switch (event_id)
{
case WEBSOCKET_EVENT_CONNECTED:
Serial.println("Connected to " + String(config.uri) + " WebSocket");
priceNotifyInit = true;
break;
case WEBSOCKET_EVENT_DATA:
onWebsocketPriceMessage(data);
break;
case WEBSOCKET_EVENT_ERROR:
Serial.println(F("Price WS Connnection error"));
break;
case WEBSOCKET_EVENT_DISCONNECTED:
Serial.println(F("Price WS Connnection Closed"));
break;
break;
case WEBSOCKET_EVENT_DATA:
onWebsocketPriceMessage(data);
break;
case WEBSOCKET_EVENT_ERROR:
Serial.println(F("Price WS Connnection error"));
break;
case WEBSOCKET_EVENT_DISCONNECTED:
Serial.println(F("Price WS Connnection Closed"));
break;
}
}
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data)
{
JsonDocument doc;
deserializeJson(doc, (char *)event_data->data_ptr);
if (doc.containsKey("bitcoin")) {
if (currentPrice != doc["bitcoin"].as<long>()) {
if (doc.containsKey("bitcoin"))
{
if (currentPrice != doc["bitcoin"].as<long>())
{
uint minSecPriceUpd = preferences.getUInt(
"minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
uint currentTime = esp_timer_get_time() / 1000000;
if (lastPriceUpdate == 0 ||
(currentTime - lastPriceUpdate) > minSecPriceUpd) {
(currentTime - lastPriceUpdate) > minSecPriceUpd)
{
// const unsigned long oldPrice = currentPrice;
currentPrice = doc["bitcoin"].as<uint>();
preferences.putUInt("lastPrice", currentPrice);
@ -95,7 +110,8 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
getCurrentScreen() == SCREEN_MSCW_TIME ||
getCurrentScreen() == SCREEN_MARKET_CAP)) {
getCurrentScreen() == SCREEN_MARKET_CAP))
{
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
}
@ -105,7 +121,8 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
}
}
uint getLastPriceUpdate() {
uint getLastPriceUpdate()
{
return lastPriceUpdate;
}
@ -113,17 +130,22 @@ uint getPrice() { return currentPrice; }
void setPrice(uint newPrice) { currentPrice = newPrice; }
bool isPriceNotifyConnected() {
if (clientPrice == NULL) return false;
bool isPriceNotifyConnected()
{
if (clientPrice == NULL)
return false;
return esp_websocket_client_is_connected(clientPrice);
}
bool getPriceNotifyInit() {
bool getPriceNotifyInit()
{
return priceNotifyInit;
}
void stopPriceNotify() {
if (clientPrice == NULL) return;
void stopPriceNotify()
{
if (clientPrice == NULL)
return;
esp_websocket_client_close(clientPrice, pdMS_TO_TICKS(5000));
esp_websocket_client_stop(clientPrice);
esp_websocket_client_destroy(clientPrice);
@ -131,9 +153,11 @@ void stopPriceNotify() {
clientPrice = NULL;
}
void restartPriceNotify() {
void restartPriceNotify()
{
stopPriceNotify();
if (clientPrice == NULL) {
if (clientPrice == NULL)
{
setupPriceNotify();
return;
}

10
src/lib/shared.cpp Normal file
View file

@ -0,0 +1,10 @@
#include "shared.hpp"
#ifdef TEST_SCREENS
uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24
uint8_t output_row_mono_buffer[max_row_width / 8]; // buffer for at least one row of b/w bits
uint8_t output_row_color_buffer[max_row_width / 8]; // buffer for at least one row of color bits
uint8_t mono_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 b/w
uint8_t color_palette_buffer[max_palette_pixels / 8]; // palette buffer for depth <= 8 c/w
uint16_t rgb_palette_buffer[max_palette_pixels]; // palette buffer for depth <= 8 for buffered graphics, needed for 7-color display
#endif

View file

@ -329,7 +329,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) {
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd",
"mdnsEnabled", "otaEnabled", "stealFocus",
"mcapBigChar", "useSatsSymbol", "useBlkCountdown",
"suffixPrice", "disableLeds"};
"suffixPrice", "disableLeds", "ownPriceSource", "flAlwaysOn"};
for (String setting : boolSettings) {
if (settings.containsKey(setting)) {
@ -425,10 +425,13 @@ void onApiSettingsGet(AsyncWebServerRequest *request) {
root["hostname"] = getMyHostname();
root["ip"] = WiFi.localIP();
root["txPower"] = WiFi.getTxPower();
root["ownPriceSource"] = preferences.getBool("ownPriceSource", true);
#ifdef HAS_FRONTLIGHT
root["hasFrontlight"] = true;
root["flMaxBrightness"] = preferences.getUInt("flMaxBrightness", 4095);
root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", false);
#else
root["hasFrontlight"] = false;
#endif