297 lines
No EOL
6.5 KiB
C++
297 lines
No EOL
6.5 KiB
C++
#define ENABLE_GxEPD2_GFX 0
|
|
|
|
#include <WiFiClient.h>
|
|
#include <ESP32Time.h>
|
|
#include <Preferences.h>
|
|
#include <ArduinoOTA.h>
|
|
|
|
#include "config.h"
|
|
#include "web.h"
|
|
#include "lib/shared.hpp"
|
|
#include "lib/functions.hpp"
|
|
#include "fonts/ubuntu-italic12.h"
|
|
#include "fonts/ubuntu-italic60.h"
|
|
|
|
Preferences preferences;
|
|
|
|
const int RST_PIN = 2;
|
|
char blocks[8];
|
|
char currentBlocks[8];
|
|
unsigned int currentScreen;
|
|
|
|
// GMT+1 is 3600 seconds time difference
|
|
ESP32Time rtc(TIME_OFFSET_SECONDS);
|
|
bool timerRunning = true;
|
|
uint timerSeconds;
|
|
String currentShownTime = "";
|
|
uint32_t moment;
|
|
uint otaProgressValue;
|
|
|
|
void showMscwTime();
|
|
void showBlockHeight();
|
|
void showBtcUsd();
|
|
void showSimpleTime();
|
|
|
|
void screenHandler(void *parameter);
|
|
void otaHandler(void *parameter);
|
|
void timebasedChange(void *parameter);
|
|
|
|
void setup()
|
|
{
|
|
Serial.begin(115200);
|
|
preferences.begin("btclock", false);
|
|
resetAllDisplays();
|
|
initDisplays();
|
|
|
|
uint initStart = millis();
|
|
|
|
#if CONFIG_LWIP_IPV6
|
|
WiFi.enableIpV6();
|
|
#endif
|
|
WiFi.hostname(OTA_NAME);
|
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
|
Serial.println("Connecting");
|
|
while (WiFi.status() != WL_CONNECTED)
|
|
{
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
|
|
WiFi.setAutoReconnect(true);
|
|
WiFi.setAutoConnect(true);
|
|
Serial.println(WiFi.localIP());
|
|
Serial.println(WiFi.localIPv6());
|
|
|
|
ArduinoOTA.onStart([]()
|
|
{
|
|
std::string text = "Update.";
|
|
|
|
showCharsInLine(text, &Ubuntu_Italic60pt7b);
|
|
delay(2000); });
|
|
|
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total)
|
|
{
|
|
if (otaProgressValue == round(int(progress / (total / 100))))
|
|
return;
|
|
otaProgressValue = round(int(progress / (total / 100)));
|
|
showChar(6, String(otaProgressValue) + "%", &Ubuntu_Italic12pt7b); });
|
|
|
|
ArduinoOTA.setHostname(OTA_NAME);
|
|
ArduinoOTA.setPassword(OTA_PASSWORD);
|
|
ArduinoOTA.begin();
|
|
|
|
// one common reset for all displays
|
|
|
|
configTime(3600, 0, NTP_SERVER);
|
|
struct tm timeinfo;
|
|
|
|
while (!getLocalTime(&timeinfo))
|
|
{
|
|
configTime(3600, 0, NTP_SERVER);
|
|
delay(500);
|
|
Serial.println("Retry set time");
|
|
}
|
|
|
|
rtc.setTimeStruct(timeinfo);
|
|
|
|
setupWebserver();
|
|
|
|
FG_COLOR = preferences.getUInt("fgColor", FG_COLOR);
|
|
BG_COLOR = preferences.getUInt("bgColor", BG_COLOR);
|
|
timerSeconds = preferences.getUInt("timerSeconds", 1800);
|
|
|
|
currentScreen = preferences.getUInt("currentScreen", 0);
|
|
Serial.print("Current screen: ");
|
|
Serial.println(currentScreen);
|
|
|
|
// Get the size of the flash memory
|
|
uint32_t flash_size = ESP.getFlashChipSize();
|
|
|
|
Serial.print("Flash size: ");
|
|
Serial.print(flash_size);
|
|
Serial.println(" bytes");
|
|
|
|
Serial.print("Waiting for display init");
|
|
while (millis() - initStart < getDisplayInitTime())
|
|
{
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
|
|
xTaskCreate(otaHandler, "ota", 10000, NULL, 10000, NULL);
|
|
xTaskCreate(screenHandler, "screen", 10000, NULL, 5, NULL);
|
|
xTaskCreate(timebasedChange, "tbc", 5000, NULL, 15, NULL);
|
|
xTaskCreate(fullRefreshWatcher, "refreshWatch", 5000, NULL, 15, NULL);
|
|
}
|
|
|
|
void loop()
|
|
{
|
|
// ArduinoOTA.handle();
|
|
}
|
|
|
|
void otaHandler(void *parameter)
|
|
{
|
|
for (;;)
|
|
{
|
|
ArduinoOTA.handle();
|
|
vTaskDelay(250 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
void screenHandler(void *parameter)
|
|
{
|
|
int displayedScreen = -1;
|
|
for (;;)
|
|
{
|
|
if (displayedScreen != currentScreen)
|
|
{
|
|
resetAllDisplays();
|
|
|
|
switch (currentScreen)
|
|
{
|
|
case SCREEN_BLOCK_HEIGHT:
|
|
showBlockHeight();
|
|
break;
|
|
case SCREEN_MSCW_TIME:
|
|
showMscwTime();
|
|
break;
|
|
case SCREEN_BTC_TICKER:
|
|
showBtcUsd();
|
|
break;
|
|
case SCREEN_TIME:
|
|
showSimpleTime();
|
|
break;
|
|
}
|
|
|
|
displayedScreen = currentScreen;
|
|
#ifdef IS_BW
|
|
}
|
|
else if (displayedScreen == SCREEN_TIME)
|
|
{
|
|
showSimpleTime();
|
|
#endif
|
|
}
|
|
|
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
void timebasedChange(void *parameter)
|
|
{
|
|
moment = millis();
|
|
|
|
for (;;)
|
|
{
|
|
if (millis() - moment > timerSeconds * 1000 && timerRunning)
|
|
{
|
|
currentScreen = (currentScreen + 1) % screenAmount;
|
|
preferences.putUInt("currentScreen", currentScreen);
|
|
moment = millis();
|
|
}
|
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
}
|
|
}
|
|
|
|
void showSimpleTime()
|
|
{
|
|
if (currentShownTime.compareTo(rtc.getTime("%H:%M").c_str()) != 0)
|
|
{
|
|
resetAllDisplays();
|
|
showNumberWithPair(String(rtc.getDay()).c_str(), String(rtc.getMonth() + 1).c_str(), rtc.getTime("%H:%M").c_str());
|
|
currentShownTime = rtc.getTime("%H:%M").c_str();
|
|
}
|
|
delay(1000);
|
|
}
|
|
|
|
void showMscwTime()
|
|
{
|
|
#ifdef DEBUG
|
|
Serial.println("Show Moscow Time");
|
|
#endif
|
|
|
|
String btcPrice = getBitcoinPrice();
|
|
|
|
std::string moscowTime = std::to_string(int(round(1 / btcPrice.toFloat() * 10e7)));
|
|
|
|
moscowTime.insert(moscowTime.begin(), 7 - moscowTime.length(), ' ');
|
|
strcpy(blocks, moscowTime.c_str());
|
|
|
|
#ifdef DEBUG
|
|
Serial.println(blocks);
|
|
#endif
|
|
static SplitText_T spd = {0, "MSCW", "TIME"};
|
|
xTaskCreate(splitTextVtask, "STv", 5000, &spd, 20, NULL);
|
|
NormalText_T data[7];
|
|
for (uint i = 1; i < 7; i++)
|
|
{
|
|
if (blocks[i] != currentBlocks[i])
|
|
{
|
|
data[i] = {i, blocks[i]};
|
|
|
|
xTaskCreate(showDigitVtask, "Disp" + char(i), 2048, &data[i], 2 + i, NULL);
|
|
}
|
|
}
|
|
|
|
std::copy(blocks, blocks + 7, currentBlocks);
|
|
delay(2000);
|
|
}
|
|
|
|
void showBtcUsd()
|
|
{
|
|
#ifdef DEBUG
|
|
Serial.println("Show BTC price");
|
|
#endif
|
|
|
|
std::string btcUsd = ("$" + getBitcoinPrice()).c_str();
|
|
|
|
btcUsd.insert(btcUsd.begin(), 7 - btcUsd.length(), ' ');
|
|
strcpy(blocks, btcUsd.c_str());
|
|
|
|
Serial.println(blocks);
|
|
|
|
static SplitText_T spd = {0, "BTC", "USD"};
|
|
xTaskCreate(splitTextVtask, "STv", 5000, &spd, 1, NULL);
|
|
|
|
NormalText_T data[7];
|
|
for (uint i = 1; i < 7; i++)
|
|
{
|
|
if (blocks[i] != currentBlocks[i])
|
|
{
|
|
data[i] = {i, blocks[i]};
|
|
|
|
xTaskCreate(showDigitVtask, "Disp" + char(i), 2048, &data[i], 2, NULL);
|
|
}
|
|
}
|
|
|
|
std::copy(blocks, blocks + 7, currentBlocks);
|
|
delay(2000);
|
|
}
|
|
|
|
void showBlockHeight()
|
|
{
|
|
#ifdef DEBUG
|
|
Serial.println("Show BlockHeight");
|
|
#endif
|
|
std::string blockNrString = getBlockHeight().c_str();
|
|
|
|
blockNrString.insert(blockNrString.begin(), 7 - blockNrString.length(), ' ');
|
|
strcpy(blocks, blockNrString.c_str());
|
|
|
|
Serial.println(blocks);
|
|
SplitText_T spd = {0, "BLOCK", "HEIGHT"};
|
|
xTaskCreate(splitTextVtask, "STv", 5000, &spd, 1, NULL);
|
|
|
|
NormalText_T data[7];
|
|
for (uint i = 1; i < 7; i++)
|
|
{
|
|
if (blocks[i] != currentBlocks[i])
|
|
{
|
|
data[i] = {i, blocks[i]};
|
|
|
|
xTaskCreate(showDigitVtask, "Disp" + char(i), 2048, &data[i], 2, NULL);
|
|
}
|
|
}
|
|
|
|
std::copy(blocks, blocks + 7, currentBlocks);
|
|
delay(2000);
|
|
} |