forked from btclock/btclock_v3
Use clang to make codestyle consistent
This commit is contained in:
parent
239415c7aa
commit
4aab02a040
31 changed files with 10588 additions and 10871 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const uint8_t Antonio_SemiBold20pt7bBitmaps[] PROGMEM = {
|
const uint8_t Antonio_SemiBold20pt7bBitmaps[] PROGMEM = {
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66,
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66,
|
||||||
0x66, 0x66, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7B, 0xDE, 0xF7,
|
0x66, 0x66, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7B, 0xDE, 0xF7,
|
||||||
|
@ -476,7 +479,6 @@ const GFXglyph Antonio_SemiBold20pt7bGlyphs[] PROGMEM = {
|
||||||
|
|
||||||
const GFXfont Antonio_SemiBold20pt7b PROGMEM = {
|
const GFXfont Antonio_SemiBold20pt7b PROGMEM = {
|
||||||
(uint8_t *)Antonio_SemiBold20pt7bBitmaps,
|
(uint8_t *)Antonio_SemiBold20pt7bBitmaps,
|
||||||
(GFXglyph *)Antonio_SemiBold20pt7bGlyphs,
|
(GFXglyph *)Antonio_SemiBold20pt7bGlyphs, 0x20, 0x7E, 51};
|
||||||
0x20, 0x7E, 51 };
|
|
||||||
|
|
||||||
// Approx. 5193 bytes
|
// Approx. 5193 bytes
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const uint8_t Antonio_SemiBold30pt7bBitmaps[] PROGMEM = {
|
const uint8_t Antonio_SemiBold30pt7bBitmaps[] PROGMEM = {
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xE7,
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xE7,
|
||||||
0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9,
|
0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9,
|
||||||
|
@ -948,7 +951,6 @@ const GFXglyph Antonio_SemiBold30pt7bGlyphs[] PROGMEM = {
|
||||||
|
|
||||||
const GFXfont Antonio_SemiBold30pt7b PROGMEM = {
|
const GFXfont Antonio_SemiBold30pt7b PROGMEM = {
|
||||||
(uint8_t *)Antonio_SemiBold30pt7bBitmaps,
|
(uint8_t *)Antonio_SemiBold30pt7bBitmaps,
|
||||||
(GFXglyph *)Antonio_SemiBold30pt7bGlyphs,
|
(GFXglyph *)Antonio_SemiBold30pt7bGlyphs, 0x20, 0x7E, 76};
|
||||||
0x20, 0x7E, 76 };
|
|
||||||
|
|
||||||
// Approx. 10860 bytes
|
// Approx. 10860 bytes
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const uint8_t Antonio_SemiBold40pt7bBitmaps[] PROGMEM = {
|
const uint8_t Antonio_SemiBold40pt7bBitmaps[] PROGMEM = {
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFE, 0x7F,
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFE, 0x7F,
|
||||||
0x9F, 0xE7, 0xF9, 0xFE, 0x7F, 0x9F, 0xE7, 0xF9, 0xFE, 0x7F, 0x9F, 0xE7,
|
0x9F, 0xE7, 0xF9, 0xFE, 0x7F, 0x9F, 0xE7, 0xF9, 0xFE, 0x7F, 0x9F, 0xE7,
|
||||||
|
@ -1624,7 +1627,6 @@ const GFXglyph Antonio_SemiBold40pt7bGlyphs[] PROGMEM = {
|
||||||
|
|
||||||
const GFXfont Antonio_SemiBold40pt7b PROGMEM = {
|
const GFXfont Antonio_SemiBold40pt7b PROGMEM = {
|
||||||
(uint8_t *)Antonio_SemiBold40pt7bBitmaps,
|
(uint8_t *)Antonio_SemiBold40pt7bBitmaps,
|
||||||
(GFXglyph *)Antonio_SemiBold40pt7bGlyphs,
|
(GFXglyph *)Antonio_SemiBold40pt7bGlyphs, 0x20, 0x7E, 101};
|
||||||
0x20, 0x7E, 101 };
|
|
||||||
|
|
||||||
// Approx. 18961 bytes
|
// Approx. 18961 bytes
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const uint8_t Antonio_SemiBold90pt7bBitmaps[] PROGMEM = {
|
const uint8_t Antonio_SemiBold90pt7bBitmaps[] PROGMEM = {
|
||||||
0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF,
|
0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF,
|
||||||
0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F,
|
0x7F, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F,
|
||||||
|
@ -5087,11 +5090,11 @@ const GFXglyph Antonio_SemiBold90pt7bGlyphs[] PROGMEM = {
|
||||||
{53398, 108, 151, 116, 4, 106}, // 0x57 'W'
|
{53398, 108, 151, 116, 4, 106}, // 0x57 'W'
|
||||||
{55437, 64, 151, 72, 4, 106}, // 0x58 'X'
|
{55437, 64, 151, 72, 4, 106}, // 0x58 'X'
|
||||||
{56645, 71, 151, 73, 1, 106}, // 0x59 'Y'
|
{56645, 71, 151, 73, 1, 106}, // 0x59 'Y'
|
||||||
{ 57986, 52, 151, 61, 6, 106 }, { 58968, 70, 155, 84, 5, 104 } }; // 0x5A 'Z'
|
{57986, 52, 151, 61, 6, 106},
|
||||||
|
{58968, 70, 155, 84, 5, 104}}; // 0x5A 'Z'
|
||||||
|
|
||||||
const GFXfont Antonio_SemiBold90pt7b PROGMEM = {
|
const GFXfont Antonio_SemiBold90pt7b PROGMEM = {
|
||||||
(uint8_t *)Antonio_SemiBold90pt7bBitmaps,
|
(uint8_t *)Antonio_SemiBold90pt7bBitmaps,
|
||||||
(GFXglyph *)Antonio_SemiBold90pt7bGlyphs,
|
(GFXglyph *)Antonio_SemiBold90pt7bGlyphs, 0x20, 0x5B, 228};
|
||||||
0x20, 0x5B, 228 };
|
|
||||||
|
|
||||||
// Approx. 60745 bytes
|
// Approx. 60745 bytes
|
||||||
|
|
|
@ -48,21 +48,19 @@ uint currentBlockHeight = 816000;
|
||||||
// ew==
|
// ew==
|
||||||
// -----END CERTIFICATE-----)";
|
// -----END CERTIFICATE-----)";
|
||||||
|
|
||||||
void setupBlockNotify()
|
void setupBlockNotify() {
|
||||||
{
|
|
||||||
// currentBlockHeight = preferences.getUInt("blockHeight", 816000);
|
// currentBlockHeight = preferences.getUInt("blockHeight", 816000);
|
||||||
|
|
||||||
IPAddress result;
|
IPAddress result;
|
||||||
|
|
||||||
int dnsErr = -1;
|
int dnsErr = -1;
|
||||||
String mempoolInstance = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
String mempoolInstance =
|
||||||
|
preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||||
|
|
||||||
while (dnsErr != 1)
|
while (dnsErr != 1) {
|
||||||
{
|
|
||||||
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
||||||
|
|
||||||
if (dnsErr != 1)
|
if (dnsErr != 1) {
|
||||||
{
|
|
||||||
Serial.print(mempoolInstance);
|
Serial.print(mempoolInstance);
|
||||||
Serial.println(F("mempool DNS could not be resolved"));
|
Serial.println(F("mempool DNS could not be resolved"));
|
||||||
WiFi.reconnect();
|
WiFi.reconnect();
|
||||||
|
@ -75,19 +73,18 @@ void setupBlockNotify()
|
||||||
http->begin("https://" + mempoolInstance + "/api/blocks/tip/height");
|
http->begin("https://" + mempoolInstance + "/api/blocks/tip/height");
|
||||||
int httpCode = http->GET();
|
int httpCode = http->GET();
|
||||||
|
|
||||||
if (httpCode > 0 && httpCode == HTTP_CODE_OK)
|
if (httpCode > 0 && httpCode == HTTP_CODE_OK) {
|
||||||
{
|
|
||||||
String blockHeightStr = http->getString();
|
String blockHeightStr = http->getString();
|
||||||
currentBlockHeight = blockHeightStr.toInt();
|
currentBlockHeight = blockHeightStr.toInt();
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
if (workQueue != nullptr)
|
if (workQueue != nullptr) {
|
||||||
{
|
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::strcpy(wsServer, String("wss://" + mempoolInstance + "/api/v1/ws").c_str());
|
// std::strcpy(wsServer, String("wss://" + mempoolInstance +
|
||||||
|
// "/api/v1/ws").c_str());
|
||||||
|
|
||||||
esp_websocket_client_config_t config = {
|
esp_websocket_client_config_t config = {
|
||||||
.uri = "wss://mempool.space/api/v1/ws",
|
.uri = "wss://mempool.space/api/v1/ws",
|
||||||
|
@ -97,22 +94,22 @@ void setupBlockNotify()
|
||||||
};
|
};
|
||||||
|
|
||||||
blockNotifyClient = esp_websocket_client_init(&config);
|
blockNotifyClient = esp_websocket_client_init(&config);
|
||||||
esp_websocket_register_events(blockNotifyClient, WEBSOCKET_EVENT_ANY, onWebsocketEvent, blockNotifyClient);
|
esp_websocket_register_events(blockNotifyClient, WEBSOCKET_EVENT_ANY,
|
||||||
|
onWebsocketEvent, blockNotifyClient);
|
||||||
esp_websocket_client_start(blockNotifyClient);
|
esp_websocket_client_start(blockNotifyClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
||||||
{
|
int32_t event_id, void *event_data) {
|
||||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||||
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\"]}";
|
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\"]}";
|
||||||
switch (event_id)
|
switch (event_id) {
|
||||||
{
|
|
||||||
case WEBSOCKET_EVENT_CONNECTED:
|
case WEBSOCKET_EVENT_CONNECTED:
|
||||||
Serial.println(F("Connected to Mempool.space WebSocket"));
|
Serial.println(F("Connected to Mempool.space WebSocket"));
|
||||||
|
|
||||||
Serial.println(sub);
|
Serial.println(sub);
|
||||||
if (esp_websocket_client_send_text(blockNotifyClient, sub.c_str(), sub.length(), portMAX_DELAY) == -1)
|
if (esp_websocket_client_send_text(blockNotifyClient, sub.c_str(),
|
||||||
{
|
sub.length(), portMAX_DELAY) == -1) {
|
||||||
Serial.println(F("Mempool.space WS Block Subscribe Error"));
|
Serial.println(F("Mempool.space WS Block Subscribe Error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,14 +126,12 @@ void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
void onWebsocketMessage(esp_websocket_event_data_t *event_data) {
|
||||||
{
|
|
||||||
SpiRamJsonDocument doc(event_data->data_len);
|
SpiRamJsonDocument doc(event_data->data_len);
|
||||||
|
|
||||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||||
|
|
||||||
if (doc.containsKey("block"))
|
if (doc.containsKey("block")) {
|
||||||
{
|
|
||||||
JsonObject block = doc["block"];
|
JsonObject block = doc["block"];
|
||||||
|
|
||||||
currentBlockHeight = block["height"].as<uint>();
|
currentBlockHeight = block["height"].as<uint>();
|
||||||
|
@ -144,14 +139,13 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
||||||
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
||||||
preferences.putUInt("blockHeight", currentBlockHeight);
|
preferences.putUInt("blockHeight", currentBlockHeight);
|
||||||
|
|
||||||
if (workQueue != nullptr)
|
if (workQueue != nullptr) {
|
||||||
{
|
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
|
||||||
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT && preferences.getBool("stealFocus", true))
|
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT &&
|
||||||
{
|
preferences.getBool("stealFocus", true)) {
|
||||||
uint64_t timerPeriod = 0;
|
uint64_t timerPeriod = 0;
|
||||||
if (isTimerActive()) {
|
if (isTimerActive()) {
|
||||||
// store timer periode before making inactive to prevent artifacts
|
// store timer periode before making inactive to prevent artifacts
|
||||||
|
@ -160,12 +154,13 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
||||||
}
|
}
|
||||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||||
if (timerPeriod > 0) {
|
if (timerPeriod > 0) {
|
||||||
esp_timer_start_periodic(screenRotateTimer, timerPeriod * usPerSecond);
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
|
timerPeriod * usPerSecond);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT && preferences.getBool("ledFlashOnUpd", false))
|
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT &&
|
||||||
{
|
preferences.getBool("ledFlashOnUpd", false)) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||||
}
|
}
|
||||||
|
@ -175,25 +170,19 @@ void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
||||||
doc.clear();
|
doc.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getBlockHeight()
|
uint getBlockHeight() { return currentBlockHeight; }
|
||||||
{
|
|
||||||
return currentBlockHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBlockHeight(uint newBlockHeight)
|
void setBlockHeight(uint newBlockHeight) {
|
||||||
{
|
|
||||||
currentBlockHeight = newBlockHeight;
|
currentBlockHeight = newBlockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBlockNotifyConnected()
|
bool isBlockNotifyConnected() {
|
||||||
{
|
|
||||||
if (blockNotifyClient == NULL)
|
if (blockNotifyClient == NULL)
|
||||||
return false;
|
return false;
|
||||||
return esp_websocket_client_is_connected(blockNotifyClient);
|
return esp_websocket_client_is_connected(blockNotifyClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopBlockNotify()
|
void stopBlockNotify() {
|
||||||
{
|
|
||||||
esp_websocket_client_stop(blockNotifyClient);
|
esp_websocket_client_stop(blockNotifyClient);
|
||||||
esp_websocket_client_destroy(blockNotifyClient);
|
esp_websocket_client_destroy(blockNotifyClient);
|
||||||
}
|
}
|
|
@ -1,21 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring>
|
#include "lib/led_handler.hpp"
|
||||||
#include <string>
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include "shared.hpp"
|
#include <HTTPClient.h>
|
||||||
#include "esp_timer.h"
|
#include <cstring>
|
||||||
#include "esp_websocket_client.h"
|
#include <esp_timer.h>
|
||||||
#include "screen_handler.hpp"
|
#include <esp_websocket_client.h>
|
||||||
#include "led_handler.hpp"
|
#include <string>
|
||||||
|
|
||||||
// using namespace websockets;
|
// using namespace websockets;
|
||||||
|
|
||||||
void setupBlockNotify();
|
void setupBlockNotify();
|
||||||
|
|
||||||
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
||||||
|
int32_t event_id, void *event_data);
|
||||||
void onWebsocketMessage(esp_websocket_event_data_t *event_data);
|
void onWebsocketMessage(esp_websocket_event_data_t *event_data);
|
||||||
|
|
||||||
void setBlockHeight(uint newBlockHeight);
|
void setBlockHeight(uint newBlockHeight);
|
||||||
|
|
|
@ -4,24 +4,19 @@ TaskHandle_t buttonTaskHandle = NULL;
|
||||||
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
||||||
TickType_t lastDebounceTime = 0;
|
TickType_t lastDebounceTime = 0;
|
||||||
|
|
||||||
void buttonTask(void *parameter)
|
void buttonTask(void *parameter) {
|
||||||
{
|
while (1) {
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||||
|
|
||||||
TickType_t currentTime = xTaskGetTickCount();
|
TickType_t currentTime = xTaskGetTickCount();
|
||||||
if ((currentTime - lastDebounceTime) >= debounceDelay)
|
if ((currentTime - lastDebounceTime) >= debounceDelay) {
|
||||||
{
|
|
||||||
lastDebounceTime = currentTime;
|
lastDebounceTime = currentTime;
|
||||||
|
|
||||||
if (!digitalRead(MCP_INT_PIN))
|
if (!digitalRead(MCP_INT_PIN)) {
|
||||||
{
|
|
||||||
uint pin = mcp1.getLastInterruptPin();
|
uint pin = mcp1.getLastInterruptPin();
|
||||||
|
|
||||||
switch (pin)
|
switch (pin) {
|
||||||
{
|
|
||||||
case 3:
|
case 3:
|
||||||
toggleTimerActive();
|
toggleTimerActive();
|
||||||
break;
|
break;
|
||||||
|
@ -37,31 +32,26 @@ void buttonTask(void *parameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mcp1.clearInterrupts();
|
mcp1.clearInterrupts();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
// Very ugly, but for some reason this is necessary
|
// Very ugly, but for some reason this is necessary
|
||||||
while (!digitalRead(MCP_INT_PIN))
|
while (!digitalRead(MCP_INT_PIN)) {
|
||||||
{
|
|
||||||
mcp1.clearInterrupts();
|
mcp1.clearInterrupts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR handleButtonInterrupt()
|
void IRAM_ATTR handleButtonInterrupt() {
|
||||||
{
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
{
|
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupButtonTask()
|
void setupButtonTask() {
|
||||||
{
|
xTaskCreate(buttonTask, "ButtonTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
xTaskCreate(buttonTask, "ButtonTask", 4096, NULL, tskIDLE_PRIORITY, &buttonTaskHandle); // Create the FreeRTOS task
|
&buttonTaskHandle); // Create the FreeRTOS task
|
||||||
// Use interrupt instead of task
|
// Use interrupt instead of task
|
||||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "shared.hpp"
|
|
||||||
#include "screen_handler.hpp"
|
|
||||||
|
|
||||||
extern TaskHandle_t buttonTaskHandle;
|
extern TaskHandle_t buttonTaskHandle;
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,16 @@ Adafruit_MCP23X17 mcp2;
|
||||||
std::vector<std::string> screenNameMap(SCREEN_COUNT);
|
std::vector<std::string> screenNameMap(SCREEN_COUNT);
|
||||||
std::mutex mcpMutex;
|
std::mutex mcpMutex;
|
||||||
|
|
||||||
void setup()
|
void setup() {
|
||||||
{
|
|
||||||
setupPreferences();
|
setupPreferences();
|
||||||
setupHardware();
|
setupHardware();
|
||||||
setupDisplays();
|
setupDisplays();
|
||||||
if (preferences.getBool("ledTestOnPower", true))
|
if (preferences.getBool("ledTestOnPower", true)) {
|
||||||
{
|
|
||||||
queueLedEffect(LED_POWER_TEST);
|
queueLedEffect(LED_POWER_TEST);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
if (mcp1.digitalRead(3) == LOW)
|
if (mcp1.digitalRead(3) == LOW) {
|
||||||
{
|
|
||||||
preferences.putBool("wifiConfigured", false);
|
preferences.putBool("wifiConfigured", false);
|
||||||
preferences.remove("txPower");
|
preferences.remove("txPower");
|
||||||
|
|
||||||
|
@ -42,7 +39,8 @@ void setup()
|
||||||
setupTasks();
|
setupTasks();
|
||||||
setupTimers();
|
setupTimers();
|
||||||
|
|
||||||
xTaskCreate(setupWebsocketClients, "setupWebsocketClients", 4096, NULL, tskIDLE_PRIORITY, NULL);
|
xTaskCreate(setupWebsocketClients, "setupWebsocketClients", 4096, NULL,
|
||||||
|
tskIDLE_PRIORITY, NULL);
|
||||||
|
|
||||||
setupButtonTask();
|
setupButtonTask();
|
||||||
setupOTA();
|
setupOTA();
|
||||||
|
@ -51,13 +49,10 @@ void setup()
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tryImprovSetup()
|
void tryImprovSetup() {
|
||||||
{
|
|
||||||
WiFi.onEvent(WiFiEvent);
|
WiFi.onEvent(WiFiEvent);
|
||||||
|
|
||||||
|
if (!preferences.getBool("wifiConfigured", false)) {
|
||||||
if (!preferences.getBool("wifiConfigured", false))
|
|
||||||
{
|
|
||||||
setFgColor(GxEPD_BLACK);
|
setFgColor(GxEPD_BLACK);
|
||||||
setBgColor(GxEPD_WHITE);
|
setBgColor(GxEPD_WHITE);
|
||||||
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
||||||
|
@ -76,42 +71,59 @@ void tryImprovSetup()
|
||||||
|
|
||||||
byte mac[6];
|
byte mac[6];
|
||||||
WiFi.macAddress(mac);
|
WiFi.macAddress(mac);
|
||||||
String softAP_SSID = String("BTClock" + String(mac[5], 16) + String(mac[1], 16));
|
String softAP_SSID =
|
||||||
|
String("BTClock" + String(mac[5], 16) + String(mac[1], 16));
|
||||||
WiFi.setHostname(softAP_SSID.c_str());
|
WiFi.setHostname(softAP_SSID.c_str());
|
||||||
String softAP_password = base64::encode(String(mac[2], 16) + String(mac[4], 16) + String(mac[5], 16) + String(mac[1], 16)).substring(2, 10);
|
String softAP_password =
|
||||||
|
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);
|
||||||
wm.setDebugOutput(false);
|
wm.setDebugOutput(false);
|
||||||
wm.setConfigPortalBlocking(true);
|
wm.setConfigPortalBlocking(true);
|
||||||
|
|
||||||
wm.setAPCallback([&](WiFiManager *wifiManager)
|
wm.setAPCallback([&](WiFiManager *wifiManager) {
|
||||||
{
|
|
||||||
|
|
||||||
// Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
|
// Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
|
||||||
// WiFi.softAPIP().toString().c_str(),
|
// WiFi.softAPIP().toString().c_str(),
|
||||||
// wifiManager->getConfigPortalSSID().c_str(),
|
// wifiManager->getConfigPortalSSID().c_str(),
|
||||||
// softAP_password.c_str());
|
// softAP_password.c_str());
|
||||||
// delay(6000);
|
// delay(6000);
|
||||||
|
|
||||||
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() + ";T:WPA;P:" + softAP_password.c_str() + ";;";
|
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() +
|
||||||
const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password;
|
";T:WPA;P:" + softAP_password.c_str() + ";;";
|
||||||
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, " ", qrText};
|
const String explainText = "*SSID: *\r\n" +
|
||||||
setEpdContent(epdContent); });
|
wifiManager->getConfigPortalSSID() +
|
||||||
|
"\r\n\r\n*Password:*\r\n" + softAP_password;
|
||||||
|
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,
|
||||||
|
" ",
|
||||||
|
qrText};
|
||||||
|
setEpdContent(epdContent);
|
||||||
|
});
|
||||||
|
|
||||||
wm.setSaveConfigCallback([]()
|
wm.setSaveConfigCallback([]() {
|
||||||
{
|
|
||||||
preferences.putBool("wifiConfigured", true);
|
preferences.putBool("wifiConfigured", true);
|
||||||
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
// just restart after succes
|
// just restart after succes
|
||||||
ESP.restart(); });
|
ESP.restart();
|
||||||
|
});
|
||||||
|
|
||||||
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
|
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
|
||||||
|
|
||||||
// waitUntilNoneBusy();
|
// waitUntilNoneBusy();
|
||||||
//std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "Bienvenidos!", "Use\r\nweb-interface\r\nto configure", "Use\r\nla interfaz web\r\npara configurar", "Or restart\r\nwhile\r\nholding\r\n2nd button\r\r\nto start\r\n QR-config", "O reinicie\r\nmientras\r\n mantiene presionado\r\nel segundo botón\r\r\npara iniciar\r\nQR-config", ""};
|
// std::array<String, NUM_SCREENS> epdContent = {"Welcome!",
|
||||||
//setEpdContent(epdContent);
|
// "Bienvenidos!", "Use\r\nweb-interface\r\nto configure", "Use\r\nla
|
||||||
|
// interfaz web\r\npara configurar", "Or
|
||||||
|
// restart\r\nwhile\r\nholding\r\n2nd button\r\r\nto start\r\n QR-config",
|
||||||
|
// "O reinicie\r\nmientras\r\n mantiene presionado\r\nel segundo
|
||||||
|
// botón\r\r\npara iniciar\r\nQR-config", ""}; setEpdContent(epdContent);
|
||||||
// esp_task_wdt_init(30, false);
|
// esp_task_wdt_init(30, false);
|
||||||
// uint count = 0;
|
// uint count = 0;
|
||||||
// while (WiFi.status() != WL_CONNECTED)
|
// while (WiFi.status() != WL_CONNECTED)
|
||||||
|
@ -120,7 +132,8 @@ void tryImprovSetup()
|
||||||
// {
|
// {
|
||||||
// uint8_t b = Serial.read();
|
// uint8_t b = Serial.read();
|
||||||
|
|
||||||
// if (parse_improv_serial_byte(x_position, b, x_buffer, onImprovCommandCallback, onImprovErrorCallback))
|
// if (parse_improv_serial_byte(x_position, b, x_buffer,
|
||||||
|
// onImprovCommandCallback, onImprovErrorCallback))
|
||||||
// {
|
// {
|
||||||
// x_buffer[x_position++] = b;
|
// x_buffer[x_position++] = b;
|
||||||
// }
|
// }
|
||||||
|
@ -138,46 +151,42 @@ void tryImprovSetup()
|
||||||
// }
|
// }
|
||||||
// esp_task_wdt_deinit();
|
// esp_task_wdt_deinit();
|
||||||
// esp_task_wdt_reset();
|
// esp_task_wdt_reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||||
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
WiFi.setAutoConnect(true);
|
WiFi.setAutoConnect(true);
|
||||||
WiFi.setAutoReconnect(true);
|
WiFi.setAutoReconnect(true);
|
||||||
WiFi.begin();
|
WiFi.begin();
|
||||||
if (preferences.getInt("txPower", 0)) {
|
if (preferences.getInt("txPower", 0)) {
|
||||||
if(WiFi.setTxPower(static_cast<wifi_power_t>(preferences.getInt("txPower", 0)))) {
|
if (WiFi.setTxPower(
|
||||||
Serial.printf("WiFi max tx power set to %d\n", preferences.getInt("txPower", 0));
|
static_cast<wifi_power_t>(preferences.getInt("txPower", 0)))) {
|
||||||
|
Serial.printf("WiFi max tx power set to %d\n",
|
||||||
|
preferences.getInt("txPower", 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
while (WiFi.status() != WL_CONNECTED)
|
|
||||||
{
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(400));
|
vTaskDelay(pdMS_TO_TICKS(400));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
// queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTime()
|
void setupTime() {
|
||||||
{
|
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
||||||
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0, NTP_SERVER);
|
NTP_SERVER);
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
|
|
||||||
while (!getLocalTime(&timeinfo))
|
while (!getLocalTime(&timeinfo)) {
|
||||||
{
|
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0,
|
||||||
configTime(preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS), 0, NTP_SERVER);
|
NTP_SERVER);
|
||||||
delay(500);
|
delay(500);
|
||||||
Serial.println(F("Retry set time"));
|
Serial.println(F("Retry set time"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPreferences()
|
void setupPreferences() {
|
||||||
{
|
|
||||||
preferences.begin("btclock", false);
|
preferences.begin("btclock", false);
|
||||||
|
|
||||||
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
|
||||||
|
@ -193,49 +202,37 @@ void setupPreferences()
|
||||||
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
screenNameMap[SCREEN_MARKET_CAP] = "Market Cap";
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWebsocketClients(void *pvParameters)
|
void setupWebsocketClients(void *pvParameters) {
|
||||||
{
|
|
||||||
setupBlockNotify();
|
setupBlockNotify();
|
||||||
|
|
||||||
if (preferences.getBool("fetchEurPrice", false))
|
if (preferences.getBool("fetchEurPrice", false)) {
|
||||||
{
|
|
||||||
setupPriceFetchTask();
|
setupPriceFetchTask();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
setupPriceNotify();
|
setupPriceNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimers()
|
void setupTimers() {
|
||||||
{
|
xTaskCreate(setupTimeUpdateTimer, "setupTimeUpdateTimer", 2048, NULL,
|
||||||
xTaskCreate(setupTimeUpdateTimer, "setupTimeUpdateTimer", 2048, NULL, tskIDLE_PRIORITY, NULL);
|
tskIDLE_PRIORITY, NULL);
|
||||||
xTaskCreate(setupScreenRotateTimer, "setupScreenRotateTimer", 2048, NULL, tskIDLE_PRIORITY, NULL);
|
xTaskCreate(setupScreenRotateTimer, "setupScreenRotateTimer", 2048, NULL,
|
||||||
|
tskIDLE_PRIORITY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void finishSetup()
|
void finishSetup() {
|
||||||
{
|
|
||||||
|
|
||||||
if (preferences.getBool("ledStatus", false))
|
if (preferences.getBool("ledStatus", false)) {
|
||||||
{
|
|
||||||
restoreLedState();
|
restoreLedState();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
clearLeds();
|
clearLeds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getScreenNameMap()
|
std::vector<std::string> getScreenNameMap() { return screenNameMap; }
|
||||||
{
|
|
||||||
return screenNameMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void setupMcp() {
|
||||||
void setupMcp()
|
|
||||||
{
|
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
const int mcp1AddrPins[] = {MCP1_A0_PIN, MCP1_A1_PIN, MCP1_A2_PIN};
|
const int mcp1AddrPins[] = {MCP1_A0_PIN, MCP1_A1_PIN, MCP1_A2_PIN};
|
||||||
const int mcp1AddrValues[] = {LOW, LOW, LOW};
|
const int mcp1AddrValues[] = {LOW, LOW, LOW};
|
||||||
|
@ -260,10 +257,8 @@ void setupMcp()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupHardware()
|
void setupHardware() {
|
||||||
{
|
if (!LittleFS.begin(true)) {
|
||||||
if (!LittleFS.begin(true))
|
|
||||||
{
|
|
||||||
Serial.println(F("An Error has occurred while mounting LittleFS"));
|
Serial.println(F("An Error has occurred while mounting LittleFS"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,9 +269,7 @@ void setupHardware()
|
||||||
setupLeds();
|
setupLeds();
|
||||||
|
|
||||||
WiFi.setHostname(getMyHostname().c_str());
|
WiFi.setHostname(getMyHostname().c_str());
|
||||||
;
|
if (!psramInit()) {
|
||||||
if (!psramInit())
|
|
||||||
{
|
|
||||||
Serial.println(F("PSRAM not available"));
|
Serial.println(F("PSRAM not available"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,34 +277,28 @@ void setupHardware()
|
||||||
|
|
||||||
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
Wire.begin(I2C_SDA_PIN, I2C_SCK_PIN, 400000);
|
||||||
|
|
||||||
if (!mcp1.begin_I2C(0x20))
|
if (!mcp1.begin_I2C(0x20)) {
|
||||||
{
|
|
||||||
Serial.println(F("Error MCP23017"));
|
Serial.println(F("Error MCP23017"));
|
||||||
|
|
||||||
// while (1)
|
// while (1)
|
||||||
// ;
|
// ;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pinMode(MCP_INT_PIN, INPUT_PULLUP);
|
pinMode(MCP_INT_PIN, INPUT_PULLUP);
|
||||||
mcp1.setupInterrupts(false, false, LOW);
|
mcp1.setupInterrupts(false, false, LOW);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++) {
|
||||||
{
|
|
||||||
mcp1.pinMode(i, INPUT_PULLUP);
|
mcp1.pinMode(i, INPUT_PULLUP);
|
||||||
mcp1.setupInterruptPin(i, LOW);
|
mcp1.setupInterruptPin(i, LOW);
|
||||||
}
|
}
|
||||||
#ifndef IS_BTCLOCK_S3
|
#ifndef IS_BTCLOCK_S3
|
||||||
for (int i = 8; i <= 14; i++)
|
for (int i = 8; i <= 14; i++) {
|
||||||
{
|
|
||||||
mcp1.pinMode(i, OUTPUT);
|
mcp1.pinMode(i, OUTPUT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
if (!mcp2.begin_I2C(0x21))
|
if (!mcp2.begin_I2C(0x21)) {
|
||||||
{
|
|
||||||
Serial.println(F("Error MCP23017"));
|
Serial.println(F("Error MCP23017"));
|
||||||
|
|
||||||
// while (1)
|
// while (1)
|
||||||
|
@ -320,34 +307,32 @@ void setupHardware()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void improvGetAvailableWifiNetworks()
|
void improvGetAvailableWifiNetworks() {
|
||||||
{
|
|
||||||
int networkNum = WiFi.scanNetworks();
|
int networkNum = WiFi.scanNetworks();
|
||||||
|
|
||||||
for (int id = 0; id < networkNum; ++id)
|
for (int id = 0; id < networkNum; ++id) {
|
||||||
{
|
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
improv::GET_WIFI_NETWORKS, {WiFi.SSID(id), String(WiFi.RSSI(id)), (WiFi.encryptionType(id) == WIFI_AUTH_OPEN ? "NO" : "YES")}, false);
|
improv::GET_WIFI_NETWORKS,
|
||||||
|
{WiFi.SSID(id), String(WiFi.RSSI(id)),
|
||||||
|
(WiFi.encryptionType(id) == WIFI_AUTH_OPEN ? "NO" : "YES")},
|
||||||
|
false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
}
|
}
|
||||||
// final response
|
// final response
|
||||||
std::vector<uint8_t> data =
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
improv::build_rpc_response(improv::GET_WIFI_NETWORKS, std::vector<std::string>{}, false);
|
improv::GET_WIFI_NETWORKS, std::vector<std::string>{}, false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool improv_connectWifi(std::string ssid, std::string password)
|
bool improv_connectWifi(std::string ssid, std::string password) {
|
||||||
{
|
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
|
|
||||||
WiFi.begin(ssid.c_str(), password.c_str());
|
WiFi.begin(ssid.c_str(), password.c_str());
|
||||||
|
|
||||||
while (WiFi.status() != WL_CONNECTED)
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
{
|
|
||||||
blinkDelay(500, 2);
|
blinkDelay(500, 2);
|
||||||
|
|
||||||
if (count > MAX_ATTEMPTS_WIFI_CONNECTION)
|
if (count > MAX_ATTEMPTS_WIFI_CONNECTION) {
|
||||||
{
|
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -357,8 +342,7 @@ bool improv_connectWifi(std::string ssid, std::string password)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onImprovErrorCallback(improv::Error err)
|
void onImprovErrorCallback(improv::Error err) {
|
||||||
{
|
|
||||||
blinkDelayColor(100, 1, 255, 0, 0);
|
blinkDelayColor(100, 1, 255, 0, 0);
|
||||||
// pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
// pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||||
// pixels.setPixelColor(1, pixels.Color(255, 0, 0));
|
// pixels.setPixelColor(1, pixels.Color(255, 0, 0));
|
||||||
|
@ -372,39 +356,29 @@ void onImprovErrorCallback(improv::Error err)
|
||||||
// vTaskDelay(pdMS_TO_TICKS(100));
|
// vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getLocalUrl()
|
std::vector<std::string> getLocalUrl() {
|
||||||
{
|
return {// URL where user can finish onboarding or use device
|
||||||
return {
|
|
||||||
// URL where user can finish onboarding or use device
|
|
||||||
// Recommended to use website hosted by device
|
// Recommended to use website hosted by device
|
||||||
String("http://" + WiFi.localIP().toString()).c_str()};
|
String("http://" + WiFi.localIP().toString()).c_str()};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
bool onImprovCommandCallback(improv::ImprovCommand cmd) {
|
||||||
{
|
switch (cmd.command) {
|
||||||
|
case improv::Command::GET_CURRENT_STATE: {
|
||||||
switch (cmd.command)
|
if ((WiFi.status() == WL_CONNECTED)) {
|
||||||
{
|
|
||||||
case improv::Command::GET_CURRENT_STATE:
|
|
||||||
{
|
|
||||||
if ((WiFi.status() == WL_CONNECTED))
|
|
||||||
{
|
|
||||||
improv_set_state(improv::State::STATE_PROVISIONED);
|
improv_set_state(improv::State::STATE_PROVISIONED);
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(improv::GET_CURRENT_STATE, getLocalUrl(), false);
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
|
improv::GET_CURRENT_STATE, getLocalUrl(), false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
improv_set_state(improv::State::STATE_AUTHORIZED);
|
improv_set_state(improv::State::STATE_AUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::WIFI_SETTINGS:
|
case improv::Command::WIFI_SETTINGS: {
|
||||||
{
|
if (cmd.ssid.length() == 0) {
|
||||||
if (cmd.ssid.length() == 0)
|
|
||||||
{
|
|
||||||
improv_set_error(improv::Error::ERROR_INVALID_RPC);
|
improv_set_error(improv::Error::ERROR_INVALID_RPC);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -412,26 +386,23 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
||||||
improv_set_state(improv::STATE_PROVISIONING);
|
improv_set_state(improv::STATE_PROVISIONING);
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECTING);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECTING);
|
||||||
|
|
||||||
if (improv_connectWifi(cmd.ssid, cmd.password))
|
if (improv_connectWifi(cmd.ssid, cmd.password)) {
|
||||||
{
|
|
||||||
|
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
|
|
||||||
// std::array<String, NUM_SCREENS> epdContent = {"S", "U", "C", "C", "E", "S", "S"};
|
// std::array<String, NUM_SCREENS> epdContent = {"S", "U", "C", "C", "E",
|
||||||
// setEpdContent(epdContent);
|
// "S", "S"}; setEpdContent(epdContent);
|
||||||
|
|
||||||
preferences.putBool("wifiConfigured", true);
|
preferences.putBool("wifiConfigured", true);
|
||||||
|
|
||||||
improv_set_state(improv::STATE_PROVISIONED);
|
improv_set_state(improv::STATE_PROVISIONED);
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(improv::WIFI_SETTINGS, getLocalUrl(), false);
|
std::vector<uint8_t> data = improv::build_rpc_response(
|
||||||
|
improv::WIFI_SETTINGS, getLocalUrl(), false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
|
|
||||||
delay(2500);
|
delay(2500);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
setupWebserver();
|
setupWebserver();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
|
|
||||||
improv_set_state(improv::STATE_STOPPED);
|
improv_set_state(improv::STATE_STOPPED);
|
||||||
|
@ -441,10 +412,8 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::GET_DEVICE_INFO:
|
case improv::Command::GET_DEVICE_INFO: {
|
||||||
{
|
std::vector<std::string> infos = {// Firmware name
|
||||||
std::vector<std::string> infos = {
|
|
||||||
// Firmware name
|
|
||||||
"BTClock",
|
"BTClock",
|
||||||
// Firmware version
|
// Firmware version
|
||||||
"1.0.0",
|
"1.0.0",
|
||||||
|
@ -452,21 +421,20 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
||||||
"ESP32S3",
|
"ESP32S3",
|
||||||
// Device name
|
// Device name
|
||||||
"BTClock"};
|
"BTClock"};
|
||||||
std::vector<uint8_t> data = improv::build_rpc_response(improv::GET_DEVICE_INFO, infos, false);
|
std::vector<uint8_t> data =
|
||||||
|
improv::build_rpc_response(improv::GET_DEVICE_INFO, infos, false);
|
||||||
improv_send_response(data);
|
improv_send_response(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case improv::Command::GET_WIFI_NETWORKS:
|
case improv::Command::GET_WIFI_NETWORKS: {
|
||||||
{
|
|
||||||
improvGetAvailableWifiNetworks();
|
improvGetAvailableWifiNetworks();
|
||||||
// std::array<String, NUM_SCREENS> epdContent = {"W", "E", "B", "W", "I", "F", "I"};
|
// std::array<String, NUM_SCREENS> epdContent = {"W", "E", "B", "W", "I",
|
||||||
// setEpdContent(epdContent);
|
// "F", "I"}; setEpdContent(epdContent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
improv_set_error(improv::ERROR_UNKNOWN_RPC);
|
improv_set_error(improv::ERROR_UNKNOWN_RPC);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -475,9 +443,7 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_set_state(improv::State state)
|
void improv_set_state(improv::State state) {
|
||||||
{
|
|
||||||
|
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(11);
|
data.resize(11);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
|
@ -493,8 +459,7 @@ void improv_set_state(improv::State state)
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_send_response(std::vector<uint8_t> &response)
|
void improv_send_response(std::vector<uint8_t> &response) {
|
||||||
{
|
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(9);
|
data.resize(9);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
|
@ -510,8 +475,7 @@ void improv_send_response(std::vector<uint8_t> &response)
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void improv_set_error(improv::Error error)
|
void improv_set_error(improv::Error error) {
|
||||||
{
|
|
||||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||||
data.resize(11);
|
data.resize(11);
|
||||||
data[6] = improv::IMPROV_SERIAL_VERSION;
|
data[6] = improv::IMPROV_SERIAL_VERSION;
|
||||||
|
@ -527,14 +491,12 @@ void improv_set_error(improv::Error error)
|
||||||
Serial.write(data.data(), data.size());
|
Serial.write(data.data(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
{
|
|
||||||
static bool first_connect = true;
|
static bool first_connect = true;
|
||||||
|
|
||||||
Serial.printf("[WiFi-event] event: %d\n", event);
|
Serial.printf("[WiFi-event] event: %d\n", event);
|
||||||
|
|
||||||
switch (event)
|
switch (event) {
|
||||||
{
|
|
||||||
case ARDUINO_EVENT_WIFI_READY:
|
case ARDUINO_EVENT_WIFI_READY:
|
||||||
Serial.println("WiFi interface ready");
|
Serial.println("WiFi interface ready");
|
||||||
break;
|
break;
|
||||||
|
@ -550,22 +512,21 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
||||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||||
Serial.println("Connected to access point");
|
Serial.println("Connected to access point");
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: {
|
||||||
{
|
|
||||||
if (!first_connect) {
|
if (!first_connect) {
|
||||||
Serial.println("Disconnected from WiFi access point");
|
Serial.println("Disconnected from WiFi access point");
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
uint8_t reason = info.wifi_sta_disconnected.reason;
|
uint8_t reason = info.wifi_sta_disconnected.reason;
|
||||||
if (reason)
|
if (reason)
|
||||||
Serial.printf("Disconnect reason: %s, ", WiFi.disconnectReasonName((wifi_err_reason_t)reason));
|
Serial.printf("Disconnect reason: %s, ",
|
||||||
|
WiFi.disconnectReasonName((wifi_err_reason_t)reason));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE:
|
||||||
Serial.println("Authentication mode of access point has changed");
|
Serial.println("Authentication mode of access point has changed");
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP: {
|
||||||
{
|
|
||||||
Serial.print("Obtained IP address: ");
|
Serial.print("Obtained IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
if (!first_connect)
|
if (!first_connect)
|
||||||
|
@ -613,7 +574,7 @@ String getMyHostname() {
|
||||||
esp_efuse_mac_get_default(mac);
|
esp_efuse_mac_get_default(mac);
|
||||||
char hostname[15];
|
char hostname[15];
|
||||||
String hostnamePrefix = preferences.getString("hostnamePrefix", "btclock");
|
String hostnamePrefix = preferences.getString("hostnamePrefix", "btclock");
|
||||||
snprintf(hostname, sizeof(hostname), "%s-%02x%02x%02x",
|
snprintf(hostname, sizeof(hostname), "%s-%02x%02x%02x", hostnamePrefix,
|
||||||
hostnamePrefix, mac[3], mac[4], mac[5]);
|
mac[3], mac[4], mac[5]);
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
|
@ -1,26 +1,23 @@
|
||||||
#pragma once;
|
#pragma once;
|
||||||
#include <WiFiManager.h>
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#include <WiFiClientSecure.h>
|
|
||||||
#include <Preferences.h>
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include <Adafruit_MCP23X17.h>
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "shared.hpp"
|
#include <Preferences.h>
|
||||||
#include "epd.hpp"
|
#include <WiFiClientSecure.h>
|
||||||
#include "improv.hpp"
|
#include <WiFiManager.h>
|
||||||
#include "esp_task_wdt.h"
|
#include <base64.h>
|
||||||
|
#include <esp_task_wdt.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "ota.hpp"
|
|
||||||
#include "lib/screen_handler.hpp"
|
|
||||||
#include "lib/webserver.hpp"
|
|
||||||
#include "lib/block_notify.hpp"
|
#include "lib/block_notify.hpp"
|
||||||
#include "lib/price_notify.hpp"
|
|
||||||
#include "lib/button_handler.hpp"
|
#include "lib/button_handler.hpp"
|
||||||
|
#include "lib/epd.hpp"
|
||||||
|
#include "lib/improv.hpp"
|
||||||
#include "lib/led_handler.hpp"
|
#include "lib/led_handler.hpp"
|
||||||
|
#include "lib/ota.hpp"
|
||||||
|
#include "lib/price_notify.hpp"
|
||||||
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
#include "lib/webserver.hpp"
|
||||||
|
|
||||||
#define NTP_SERVER "pool.ntp.org"
|
#define NTP_SERVER "pool.ntp.org"
|
||||||
#define DEFAULT_MEMPOOL_INSTANCE "mempool.space"
|
#define DEFAULT_MEMPOOL_INSTANCE "mempool.space"
|
||||||
|
|
271
src/lib/epd.cpp
271
src/lib/epd.cpp
|
@ -16,21 +16,12 @@ Native_Pin EPD_CS[NUM_SCREENS] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
Native_Pin(3),
|
Native_Pin(3), Native_Pin(5), Native_Pin(7), Native_Pin(9),
|
||||||
Native_Pin(5),
|
Native_Pin(37), Native_Pin(18), Native_Pin(16),
|
||||||
Native_Pin(7),
|
|
||||||
Native_Pin(9),
|
|
||||||
Native_Pin(37),
|
|
||||||
Native_Pin(18),
|
|
||||||
Native_Pin(16),
|
|
||||||
};
|
};
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8),
|
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
||||||
MCP23X17_Pin(mcp1, 9),
|
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
||||||
MCP23X17_Pin(mcp1, 10),
|
|
||||||
MCP23X17_Pin(mcp1, 11),
|
|
||||||
MCP23X17_Pin(mcp1, 12),
|
|
||||||
MCP23X17_Pin(mcp1, 13),
|
|
||||||
MCP23X17_Pin(mcp1, 14),
|
MCP23X17_Pin(mcp1, 14),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,36 +30,20 @@ Native_Pin EPD_DC = Native_Pin(14);
|
||||||
Native_Pin EPD_DC = Native_Pin(38);
|
Native_Pin EPD_DC = Native_Pin(38);
|
||||||
|
|
||||||
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8),
|
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
||||||
MCP23X17_Pin(mcp1, 9),
|
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
||||||
MCP23X17_Pin(mcp1, 10),
|
MCP23X17_Pin(mcp1, 14), MCP23X17_Pin(mcp1, 4),
|
||||||
MCP23X17_Pin(mcp1, 11),
|
|
||||||
MCP23X17_Pin(mcp1, 12),
|
|
||||||
MCP23X17_Pin(mcp1, 13),
|
|
||||||
MCP23X17_Pin(mcp1, 14),
|
|
||||||
MCP23X17_Pin(mcp1, 4),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp2, 8),
|
MCP23X17_Pin(mcp2, 8), MCP23X17_Pin(mcp2, 10), MCP23X17_Pin(mcp2, 12),
|
||||||
MCP23X17_Pin(mcp2, 10),
|
MCP23X17_Pin(mcp2, 14), MCP23X17_Pin(mcp2, 0), MCP23X17_Pin(mcp2, 2),
|
||||||
MCP23X17_Pin(mcp2, 12),
|
MCP23X17_Pin(mcp2, 4), MCP23X17_Pin(mcp2, 6)};
|
||||||
MCP23X17_Pin(mcp2, 14),
|
|
||||||
MCP23X17_Pin(mcp2, 0),
|
|
||||||
MCP23X17_Pin(mcp2, 2),
|
|
||||||
MCP23X17_Pin(mcp2, 4),
|
|
||||||
MCP23X17_Pin(mcp2, 6)
|
|
||||||
};
|
|
||||||
|
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp2, 9),
|
MCP23X17_Pin(mcp2, 9), MCP23X17_Pin(mcp2, 11), MCP23X17_Pin(mcp2, 13),
|
||||||
MCP23X17_Pin(mcp2, 11),
|
MCP23X17_Pin(mcp2, 15), MCP23X17_Pin(mcp2, 1), MCP23X17_Pin(mcp2, 3),
|
||||||
MCP23X17_Pin(mcp2, 13),
|
MCP23X17_Pin(mcp2, 5), MCP23X17_Pin(mcp2, 7),
|
||||||
MCP23X17_Pin(mcp2, 15),
|
|
||||||
MCP23X17_Pin(mcp2, 1),
|
|
||||||
MCP23X17_Pin(mcp2, 3),
|
|
||||||
MCP23X17_Pin(mcp2, 5),
|
|
||||||
MCP23X17_Pin(mcp2, 7),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,37 +83,32 @@ std::mutex epdMutex[NUM_SCREENS];
|
||||||
|
|
||||||
uint8_t qrcode[800];
|
uint8_t qrcode[800];
|
||||||
|
|
||||||
void forceFullRefresh()
|
void forceFullRefresh() {
|
||||||
{
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
lastFullRefresh[i] = NULL;
|
lastFullRefresh[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshFromMemory()
|
void refreshFromMemory() {
|
||||||
{
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
int *taskParam = new int;
|
int *taskParam = new int;
|
||||||
*taskParam = i;
|
*taskParam = i;
|
||||||
|
|
||||||
xTaskCreate([](void *pvParameters)
|
xTaskCreate(
|
||||||
{
|
[](void *pvParameters) {
|
||||||
const int epdIndex = *(int *)pvParameters;
|
const int epdIndex = *(int *)pvParameters;
|
||||||
delete (int *)pvParameters;
|
delete (int *)pvParameters;
|
||||||
displays[epdIndex].refresh(false);
|
displays[epdIndex].refresh(false);
|
||||||
vTaskDelete(NULL); },
|
vTaskDelete(NULL);
|
||||||
|
},
|
||||||
"PrepareUpd", 4096, taskParam, tskIDLE_PRIORITY, NULL);
|
"PrepareUpd", 4096, taskParam, tskIDLE_PRIORITY, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDisplays()
|
void setupDisplays() {
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
{
|
|
||||||
displays[i].init(0, true, 30);
|
displays[i].init(0, true, 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,30 +116,23 @@ void setupDisplays()
|
||||||
|
|
||||||
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
{
|
|
||||||
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
||||||
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
||||||
|
|
||||||
int *taskParam = new int;
|
int *taskParam = new int;
|
||||||
*taskParam = i;
|
*taskParam = i;
|
||||||
|
|
||||||
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 2048, taskParam, 11, &tasks[i]); // create task
|
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 2048, taskParam,
|
||||||
|
11, &tasks[i]); // create task
|
||||||
}
|
}
|
||||||
|
|
||||||
epdContent = {"B",
|
epdContent = {"B", "T", "C", "L", "O", "C", "K"};
|
||||||
"T",
|
|
||||||
"C",
|
|
||||||
"L",
|
|
||||||
"O",
|
|
||||||
"C",
|
|
||||||
"K"};
|
|
||||||
|
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent)
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent) {
|
||||||
{
|
|
||||||
setEpdContent(newEpdContent, false);
|
setEpdContent(newEpdContent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,16 +146,14 @@ void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent) {
|
||||||
return setEpdContent(conv);
|
return setEpdContent(conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent, bool forceUpdate)
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
||||||
{
|
bool forceUpdate) {
|
||||||
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
||||||
|
|
||||||
waitUntilNoneBusy();
|
waitUntilNoneBusy();
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
{
|
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate) {
|
||||||
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate)
|
|
||||||
{
|
|
||||||
epdContent[i] = newEpdContent[i];
|
epdContent[i] = newEpdContent[i];
|
||||||
UpdateDisplayTaskItem dispUpdate = {i};
|
UpdateDisplayTaskItem dispUpdate = {i};
|
||||||
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
||||||
|
@ -200,45 +161,37 @@ void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent, bool forceUpda
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareDisplayUpdateTask(void *pvParameters)
|
void prepareDisplayUpdateTask(void *pvParameters) {
|
||||||
{
|
|
||||||
UpdateDisplayTaskItem receivedItem;
|
UpdateDisplayTaskItem receivedItem;
|
||||||
|
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
// Wait for a work item to be available in the queue
|
// Wait for a work item to be available in the queue
|
||||||
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY))
|
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY)) {
|
||||||
{
|
|
||||||
uint epdIndex = receivedItem.dispNum;
|
uint epdIndex = receivedItem.dispNum;
|
||||||
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
||||||
// displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
// displays[epdIndex].init(0, false); // Little longer reset duration
|
||||||
|
// because of MCP
|
||||||
|
|
||||||
bool updatePartial = true;
|
bool updatePartial = true;
|
||||||
|
|
||||||
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL) {
|
||||||
{
|
String top = epdContent[epdIndex].substring(
|
||||||
String top = epdContent[epdIndex].substring(0, epdContent[epdIndex].indexOf("/"));
|
0, epdContent[epdIndex].indexOf("/"));
|
||||||
String bottom = epdContent[epdIndex].substring(epdContent[epdIndex].indexOf("/") + 1);
|
String bottom = epdContent[epdIndex].substring(
|
||||||
|
epdContent[epdIndex].indexOf("/") + 1);
|
||||||
splitText(epdIndex, top, bottom, updatePartial);
|
splitText(epdIndex, top, bottom, updatePartial);
|
||||||
}
|
} else if (epdContent[epdIndex].startsWith(F("qr"))) {
|
||||||
else if (epdContent[epdIndex].startsWith(F("qr")))
|
|
||||||
{
|
|
||||||
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
}
|
} else if (epdContent[epdIndex].length() > 5) {
|
||||||
else if (epdContent[epdIndex].length() > 5)
|
|
||||||
{
|
|
||||||
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
if (epdContent[epdIndex].length() > 1)
|
if (epdContent[epdIndex].length() > 1) {
|
||||||
{
|
showChars(epdIndex, epdContent[epdIndex], updatePartial,
|
||||||
showChars(epdIndex, epdContent[epdIndex], updatePartial, &FONT_MEDIUM);
|
&FONT_MEDIUM);
|
||||||
}
|
} else {
|
||||||
else
|
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial,
|
||||||
{
|
&FONT_BIG);
|
||||||
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,13 +200,11 @@ void prepareDisplayUpdateTask(void *pvParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept
|
extern "C" void updateDisplay(void *pvParameters) noexcept {
|
||||||
{
|
|
||||||
const int epdIndex = *(int *)pvParameters;
|
const int epdIndex = *(int *)pvParameters;
|
||||||
delete (int *)pvParameters;
|
delete (int *)pvParameters;
|
||||||
|
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
// Wait for the task notification
|
// Wait for the task notification
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
@ -265,8 +216,7 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
displays[epdIndex].init(0, false, 40);
|
displays[epdIndex].init(0, false, 40);
|
||||||
}
|
}
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
|
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) {
|
||||||
{
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -274,16 +224,17 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
bool updatePartial = true;
|
bool updatePartial = true;
|
||||||
|
|
||||||
// Full Refresh every x minutes
|
// Full Refresh every x minutes
|
||||||
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", DEFAULT_MINUTES_FULL_REFRESH) * 60 * 1000))
|
if (!lastFullRefresh[epdIndex] ||
|
||||||
{
|
(millis() - lastFullRefresh[epdIndex]) >
|
||||||
|
(preferences.getUInt("fullRefreshMin",
|
||||||
|
DEFAULT_MINUTES_FULL_REFRESH) *
|
||||||
|
60 * 1000)) {
|
||||||
updatePartial = false;
|
updatePartial = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char tries = 0;
|
char tries = 0;
|
||||||
while (tries < 3)
|
while (tries < 3) {
|
||||||
{
|
if (displays[epdIndex].displayWithReturn(updatePartial)) {
|
||||||
if (displays[epdIndex].displayWithReturn(updatePartial))
|
|
||||||
{
|
|
||||||
displays[epdIndex].powerOff();
|
displays[epdIndex].powerOff();
|
||||||
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
||||||
if (!updatePartial)
|
if (!updatePartial)
|
||||||
|
@ -301,8 +252,8 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String &top, const String &bottom, bool partial)
|
void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
{
|
bool partial) {
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(&FONT_SMALL);
|
displays[dispNum].setFont(&FONT_SMALL);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
@ -312,14 +263,16 @@ void splitText(const uint dispNum, const String &top, const String &bottom, bool
|
||||||
uint16_t ttbw, ttbh;
|
uint16_t ttbw, ttbh;
|
||||||
displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
||||||
uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
||||||
uint16_t ty = ((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
uint16_t ty =
|
||||||
|
((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
||||||
|
|
||||||
// Bottom text
|
// Bottom text
|
||||||
int16_t tbbx, tbby;
|
int16_t tbbx, tbby;
|
||||||
uint16_t tbbw, tbbh;
|
uint16_t tbbw, tbbh;
|
||||||
displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
||||||
uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
||||||
uint16_t by = ((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
uint16_t by =
|
||||||
|
((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
||||||
|
|
||||||
// Make separator as wide as the shortest text.
|
// Make separator as wide as the shortest text.
|
||||||
uint16_t lineWidth, lineX;
|
uint16_t lineWidth, lineX;
|
||||||
|
@ -332,13 +285,14 @@ void splitText(const uint dispNum, const String &top, const String &bottom, bool
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
displays[dispNum].setCursor(tx, ty);
|
displays[dispNum].setCursor(tx, ty);
|
||||||
displays[dispNum].print(top);
|
displays[dispNum].print(top);
|
||||||
displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3, lineWidth, 6, 3, getFgColor());
|
displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3,
|
||||||
|
lineWidth, 6, 3, getFgColor());
|
||||||
displays[dispNum].setCursor(bx, by);
|
displays[dispNum].setCursor(bx, by);
|
||||||
displays[dispNum].print(bottom);
|
displays[dispNum].print(bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
void showDigit(const uint dispNum, char chr, bool partial,
|
||||||
{
|
const GFXfont *font) {
|
||||||
String str(chr);
|
String str(chr);
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
displays[dispNum].setFont(font);
|
||||||
|
@ -354,8 +308,8 @@ void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
||||||
displays[dispNum].print(str);
|
displays[dispNum].print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showChars(const uint dispNum, const String &chars, bool partial, const GFXfont *font)
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
{
|
const GFXfont *font) {
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setFont(font);
|
displays[dispNum].setFont(font);
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
@ -370,34 +324,21 @@ void showChars(const uint dispNum, const String &chars, bool partial, const GFXf
|
||||||
displays[dispNum].print(chars);
|
displays[dispNum].print(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBgColor()
|
int getBgColor() { return bgColor; }
|
||||||
{
|
|
||||||
return bgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getFgColor()
|
int getFgColor() { return fgColor; }
|
||||||
{
|
|
||||||
return fgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBgColor(int color)
|
void setBgColor(int color) { bgColor = color; }
|
||||||
{
|
|
||||||
bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFgColor(int color)
|
void setFgColor(int color) { fgColor = color; }
|
||||||
{
|
|
||||||
fgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> getCurrentEpdContent()
|
std::array<String, NUM_SCREENS> getCurrentEpdContent() {
|
||||||
{
|
|
||||||
return currentEpdContent;
|
return currentEpdContent;
|
||||||
}
|
}
|
||||||
void renderText(const uint dispNum, const String &text, bool partial)
|
void renderText(const uint dispNum, const String &text, bool partial) {
|
||||||
{
|
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
|
displays[dispNum].height());
|
||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
displays[dispNum].setTextColor(GxEPD_BLACK);
|
displays[dispNum].setTextColor(GxEPD_BLACK);
|
||||||
displays[dispNum].setCursor(0, 50);
|
displays[dispNum].setCursor(0, 50);
|
||||||
|
@ -407,67 +348,61 @@ void renderText(const uint dispNum, const String &text, bool partial)
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
while (std::getline(ss, line, '\n'))
|
while (std::getline(ss, line, '\n')) {
|
||||||
{
|
if (line.rfind("*", 0) == 0) {
|
||||||
if (line.rfind("*", 0) == 0)
|
|
||||||
{
|
|
||||||
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
||||||
|
|
||||||
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
||||||
displays[dispNum].println(line.c_str());
|
displays[dispNum].println(line.c_str());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
displays[dispNum].setFont(&FreeSans9pt7b);
|
displays[dispNum].setFont(&FreeSans9pt7b);
|
||||||
displays[dispNum].println(line.c_str());
|
displays[dispNum].println(line.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
void renderQr(const uint dispNum, const String &text, bool partial) {
|
||||||
{
|
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
|
|
||||||
uint8_t tempBuffer[800];
|
uint8_t tempBuffer[800];
|
||||||
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
bool ok = qrcodegen_encodeText(
|
||||||
|
text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||||
|
|
||||||
const int size = qrcodegen_getSize(qrcode);
|
const int size = qrcodegen_getSize(qrcode);
|
||||||
|
|
||||||
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
||||||
const int paddingY = floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
const int paddingY =
|
||||||
|
floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
||||||
displays[dispNum].setRotation(2);
|
displays[dispNum].setRotation(2);
|
||||||
|
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
|
displays[dispNum].height());
|
||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
const int border = 0;
|
const int border = 0;
|
||||||
|
|
||||||
for (int y = -border; y < size * 4 + border; y++)
|
for (int y = -border; y < size * 4 + border; y++) {
|
||||||
{
|
for (int x = -border; x < size * 4 + border; x++) {
|
||||||
for (int x = -border; x < size * 4 + border; x++)
|
displays[dispNum].drawPixel(
|
||||||
{
|
padding + x, paddingY + y,
|
||||||
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
||||||
|
? GxEPD_BLACK
|
||||||
|
: GxEPD_WHITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitUntilNoneBusy()
|
void waitUntilNoneBusy() {
|
||||||
{
|
for (int i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (int i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
uint count = 0;
|
uint count = 0;
|
||||||
while (EPD_BUSY[i].digitalRead())
|
while (EPD_BUSY[i].digitalRead()) {
|
||||||
{
|
|
||||||
count++;
|
count++;
|
||||||
vTaskDelay(10);
|
vTaskDelay(10);
|
||||||
if (count == 200)
|
if (count == 200) {
|
||||||
{
|
|
||||||
// displays[i].init(0, false);
|
// displays[i].init(0, false);
|
||||||
vTaskDelay(100);
|
vTaskDelay(100);
|
||||||
}
|
} else if (count > 205) {
|
||||||
else if (count > 205)
|
|
||||||
{
|
|
||||||
Serial.printf("Busy timeout %d", i);
|
Serial.printf("Busy timeout %d", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <GxEPD2_BW.h>
|
|
||||||
#include <native_pin.hpp>
|
|
||||||
#include <mcp23x17_pin.hpp>
|
|
||||||
#include "shared.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "fonts/fonts.hpp"
|
#include "fonts/fonts.hpp"
|
||||||
#include <Fonts/FreeSansBold9pt7b.h>
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Fonts/FreeSans9pt7b.h>
|
#include <Fonts/FreeSans9pt7b.h>
|
||||||
#include <regex>
|
#include <Fonts/FreeSansBold9pt7b.h>
|
||||||
|
#include <GxEPD2_BW.h>
|
||||||
|
#include <mcp23x17_pin.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <native_pin.hpp>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
#include "qrcodegen.h"
|
#include "qrcodegen.h"
|
||||||
#endif
|
#endif
|
||||||
// extern TaskHandle_t epdTaskHandle;
|
// extern TaskHandle_t epdTaskHandle;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
char dispNum;
|
char dispNum;
|
||||||
} UpdateDisplayTaskItem;
|
} UpdateDisplayTaskItem;
|
||||||
|
|
||||||
|
@ -25,10 +24,12 @@ void forceFullRefresh();
|
||||||
void refreshFromMemory();
|
void refreshFromMemory();
|
||||||
void setupDisplays();
|
void setupDisplays();
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String& top, const String& bottom, bool partial);
|
void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
|
bool partial);
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font);
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
|
const GFXfont *font);
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
||||||
void updateDisplayAlt(int epdIndex);
|
void updateDisplayAlt(int epdIndex);
|
||||||
|
@ -42,7 +43,8 @@ void setFgColor(int color);
|
||||||
void renderText(const uint dispNum, const String &text, bool partial);
|
void renderText(const uint dispNum, const String &text, bool partial);
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial);
|
void renderQr(const uint dispNum, const String &text, bool partial);
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent, bool forceUpdate);
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
||||||
|
bool forceUpdate);
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent);
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent);
|
||||||
|
|
||||||
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent);
|
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent);
|
||||||
|
|
|
@ -2,11 +2,13 @@
|
||||||
|
|
||||||
namespace improv {
|
namespace improv {
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data, bool check_checksum) {
|
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data,
|
||||||
|
bool check_checksum) {
|
||||||
return parse_improv_data(data.data(), data.size(), check_checksum);
|
return parse_improv_data(data.data(), data.size(), check_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_checksum) {
|
ImprovCommand parse_improv_data(const uint8_t *data, size_t length,
|
||||||
|
bool check_checksum) {
|
||||||
ImprovCommand improv_command;
|
ImprovCommand improv_command;
|
||||||
Command command = (Command)data[0];
|
Command command = (Command)data[0];
|
||||||
uint8_t data_length = data[1];
|
uint8_t data_length = data[1];
|
||||||
|
@ -48,8 +50,10 @@ ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_c
|
||||||
return improv_command;
|
return improv_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buffer,
|
bool parse_improv_serial_byte(size_t position, uint8_t byte,
|
||||||
std::function<bool(ImprovCommand)> &&callback, std::function<void(Error)> &&on_error) {
|
const uint8_t *buffer,
|
||||||
|
std::function<bool(ImprovCommand)> &&callback,
|
||||||
|
std::function<void(Error)> &&on_error) {
|
||||||
if (position == 0)
|
if (position == 0)
|
||||||
return byte == 'I';
|
return byte == 'I';
|
||||||
if (position == 1)
|
if (position == 1)
|
||||||
|
@ -94,7 +98,9 @@ bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buff
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::string> &datum, bool add_checksum) {
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<std::string> &datum,
|
||||||
|
bool add_checksum) {
|
||||||
std::vector<uint8_t> out;
|
std::vector<uint8_t> out;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
out.push_back(command);
|
out.push_back(command);
|
||||||
|
@ -118,7 +124,9 @@ std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<String> &datum, bool add_checksum) {
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<String> &datum,
|
||||||
|
bool add_checksum) {
|
||||||
std::vector<uint8_t> out;
|
std::vector<uint8_t> out;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
out.push_back(command);
|
out.push_back(command);
|
||||||
|
|
|
@ -14,9 +14,12 @@ namespace improv {
|
||||||
static const char *const SERVICE_UUID = "00467768-6228-2272-4663-277478268000";
|
static const char *const SERVICE_UUID = "00467768-6228-2272-4663-277478268000";
|
||||||
static const char *const STATUS_UUID = "00467768-6228-2272-4663-277478268001";
|
static const char *const STATUS_UUID = "00467768-6228-2272-4663-277478268001";
|
||||||
static const char *const ERROR_UUID = "00467768-6228-2272-4663-277478268002";
|
static const char *const ERROR_UUID = "00467768-6228-2272-4663-277478268002";
|
||||||
static const char *const RPC_COMMAND_UUID = "00467768-6228-2272-4663-277478268003";
|
static const char *const RPC_COMMAND_UUID =
|
||||||
static const char *const RPC_RESULT_UUID = "00467768-6228-2272-4663-277478268004";
|
"00467768-6228-2272-4663-277478268003";
|
||||||
static const char *const CAPABILITIES_UUID = "00467768-6228-2272-4663-277478268005";
|
static const char *const RPC_RESULT_UUID =
|
||||||
|
"00467768-6228-2272-4663-277478268004";
|
||||||
|
static const char *const CAPABILITIES_UUID =
|
||||||
|
"00467768-6228-2272-4663-277478268005";
|
||||||
|
|
||||||
enum Error : uint8_t {
|
enum Error : uint8_t {
|
||||||
ERROR_NONE = 0x00,
|
ERROR_NONE = 0x00,
|
||||||
|
@ -61,16 +64,23 @@ struct ImprovCommand {
|
||||||
std::string password;
|
std::string password;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data, bool check_checksum = true);
|
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data,
|
||||||
ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_checksum = true);
|
bool check_checksum = true);
|
||||||
|
ImprovCommand parse_improv_data(const uint8_t *data, size_t length,
|
||||||
|
bool check_checksum = true);
|
||||||
|
|
||||||
bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buffer,
|
bool parse_improv_serial_byte(size_t position, uint8_t byte,
|
||||||
std::function<bool(ImprovCommand)> &&callback, std::function<void(Error)> &&on_error);
|
const uint8_t *buffer,
|
||||||
|
std::function<bool(ImprovCommand)> &&callback,
|
||||||
|
std::function<void(Error)> &&on_error);
|
||||||
|
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::string> &datum,
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<std::string> &datum,
|
||||||
bool add_checksum = true);
|
bool add_checksum = true);
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<String> &datum, bool add_checksum = true);
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<String> &datum,
|
||||||
|
bool add_checksum = true);
|
||||||
#endif // ARDUINO
|
#endif // ARDUINO
|
||||||
|
|
||||||
} // namespace improv
|
} // namespace improv
|
|
@ -5,30 +5,26 @@ QueueHandle_t ledTaskQueue = NULL;
|
||||||
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
||||||
uint ledTaskParams;
|
uint ledTaskParams;
|
||||||
|
|
||||||
void ledTask(void *parameter)
|
void ledTask(void *parameter) {
|
||||||
{
|
while (1) {
|
||||||
while (1)
|
if (ledTaskQueue != NULL) {
|
||||||
{
|
if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) ==
|
||||||
if (ledTaskQueue != NULL)
|
pdPASS) {
|
||||||
{
|
|
||||||
if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) == pdPASS)
|
|
||||||
{
|
|
||||||
uint32_t oldLights[NEOPIXEL_COUNT];
|
uint32_t oldLights[NEOPIXEL_COUNT];
|
||||||
|
|
||||||
// get current state
|
// get current state
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
|
||||||
oldLights[i] = pixels.getPixelColor(i);
|
oldLights[i] = pixels.getPixelColor(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ledTaskParams)
|
switch (ledTaskParams) {
|
||||||
{
|
|
||||||
case LED_POWER_TEST:
|
case LED_POWER_TEST:
|
||||||
ledRainbow(20);
|
ledRainbow(20);
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_WIFI_CONNECT_ERROR:
|
case LED_EFFECT_WIFI_CONNECT_ERROR:
|
||||||
blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236), pixels.Color(255, 0, 0));
|
blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236),
|
||||||
|
pixels.Color(255, 0, 0));
|
||||||
break;
|
break;
|
||||||
case LED_FLASH_ERROR:
|
case LED_FLASH_ERROR:
|
||||||
blinkDelayColor(250, 3, 255, 0, 0);
|
blinkDelayColor(250, 3, 255, 0, 0);
|
||||||
|
@ -53,25 +49,22 @@ void ledTask(void *parameter)
|
||||||
case LED_FLASH_UPDATE:
|
case LED_FLASH_UPDATE:
|
||||||
break;
|
break;
|
||||||
case LED_FLASH_BLOCK_NOTIFY:
|
case LED_FLASH_BLOCK_NOTIFY:
|
||||||
blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0), pixels.Color(8, 2, 0));
|
blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0),
|
||||||
|
pixels.Color(8, 2, 0));
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
|
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
|
||||||
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), pixels.Color(156, 225, 240));
|
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236),
|
||||||
|
pixels.Color(156, 225, 240));
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_WIFI_ERASE_SETTINGS:
|
case LED_EFFECT_WIFI_ERASE_SETTINGS:
|
||||||
blinkDelay(100, 3);
|
blinkDelay(100, 3);
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_WIFI_CONNECTING:
|
case LED_EFFECT_WIFI_CONNECTING:
|
||||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
for (int i = NEOPIXEL_COUNT; i >= 0; i--) {
|
||||||
{
|
for (int j = NEOPIXEL_COUNT; j >= 0; j--) {
|
||||||
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
|
if (j == i) {
|
||||||
{
|
|
||||||
if (j == i)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, pixels.Color(16, 197, 236));
|
pixels.setPixelColor(i, pixels.Color(16, 197, 236));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(j, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(j, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,10 +73,8 @@ void ledTask(void *parameter)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_PAUSE_TIMER:
|
case LED_EFFECT_PAUSE_TIMER:
|
||||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
for (int i = NEOPIXEL_COUNT; i >= 0; i--) {
|
||||||
{
|
for (int j = NEOPIXEL_COUNT; j >= 0; j--) {
|
||||||
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
|
|
||||||
{
|
|
||||||
uint32_t c = pixels.Color(0, 0, 0);
|
uint32_t c = pixels.Color(0, 0, 0);
|
||||||
if (i == j)
|
if (i == j)
|
||||||
c = pixels.Color(0, 255, 0);
|
c = pixels.Color(0, 255, 0);
|
||||||
|
@ -109,11 +100,9 @@ void ledTask(void *parameter)
|
||||||
|
|
||||||
delay(900);
|
delay(900);
|
||||||
|
|
||||||
for (int i = NEOPIXEL_COUNT; i--; i > 0)
|
for (int i = NEOPIXEL_COUNT; i--; i > 0) {
|
||||||
{
|
|
||||||
|
|
||||||
for (int j = NEOPIXEL_COUNT; j--; j > 0)
|
for (int j = NEOPIXEL_COUNT; j--; j > 0) {
|
||||||
{
|
|
||||||
uint32_t c = pixels.Color(0, 0, 0);
|
uint32_t c = pixels.Color(0, 0, 0);
|
||||||
if (i == j)
|
if (i == j)
|
||||||
c = pixels.Color(0, 255, 0);
|
c = pixels.Color(0, 255, 0);
|
||||||
|
@ -133,8 +122,7 @@ void ledTask(void *parameter)
|
||||||
|
|
||||||
// revert to previous state unless power test
|
// revert to previous state unless power test
|
||||||
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, oldLights[i]);
|
pixels.setPixelColor(i, oldLights[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,17 +132,14 @@ void ledTask(void *parameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupLeds()
|
void setupLeds() {
|
||||||
{
|
|
||||||
pixels.begin();
|
pixels.begin();
|
||||||
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
pixels.show();
|
pixels.show();
|
||||||
setupLedTask();
|
setupLedTask();
|
||||||
if (preferences.getBool("ledTestOnPower", true))
|
if (preferences.getBool("ledTestOnPower", true)) {
|
||||||
{
|
while (!ledTaskQueue) {
|
||||||
while (!ledTaskQueue)
|
|
||||||
{
|
|
||||||
delay(1);
|
delay(1);
|
||||||
// wait until queue is available
|
// wait until queue is available
|
||||||
}
|
}
|
||||||
|
@ -162,17 +147,14 @@ void setupLeds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupLedTask()
|
void setupLedTask() {
|
||||||
{
|
|
||||||
ledTaskQueue = xQueueCreate(5, sizeof(uint));
|
ledTaskQueue = xQueueCreate(5, sizeof(uint));
|
||||||
|
|
||||||
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
|
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blinkDelay(int d, int times)
|
void blinkDelay(int d, int times) {
|
||||||
{
|
for (int j = 0; j < times; j++) {
|
||||||
for (int j = 0; j < times; j++)
|
|
||||||
{
|
|
||||||
|
|
||||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||||
|
@ -192,12 +174,9 @@ void blinkDelay(int d, int times)
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void blinkDelayColor(int d, int times, uint r, uint g, uint b)
|
void blinkDelayColor(int d, int times, uint r, uint g, uint b) {
|
||||||
{
|
for (int j = 0; j < times; j++) {
|
||||||
for (int j = 0; j < times; j++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, pixels.Color(r, g, b));
|
pixels.setPixelColor(i, pixels.Color(r, g, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,19 +191,15 @@ void blinkDelayColor(int d, int times, uint r, uint g, uint b)
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2)
|
void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2) {
|
||||||
{
|
for (int j = 0; j < times; j++) {
|
||||||
for (int j = 0; j < times; j++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, c1);
|
pixels.setPixelColor(i, c1);
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, c2);
|
pixels.setPixelColor(i, c2);
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
|
@ -234,43 +209,33 @@ void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2)
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearLeds()
|
void clearLeds() {
|
||||||
{
|
|
||||||
preferences.putBool("ledStatus", false);
|
preferences.putBool("ledStatus", false);
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLights(int r, int g, int b)
|
void setLights(int r, int g, int b) { setLights(pixels.Color(r, g, b)); }
|
||||||
{
|
|
||||||
setLights(pixels.Color(r, g, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLights(uint32_t color)
|
void setLights(uint32_t color) {
|
||||||
{
|
|
||||||
|
|
||||||
bool ledStatus = true;
|
bool ledStatus = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, color);
|
pixels.setPixelColor(i, color);
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
|
|
||||||
if (color == pixels.Color(0, 0, 0))
|
if (color == pixels.Color(0, 0, 0)) {
|
||||||
{
|
|
||||||
ledStatus = false;
|
ledStatus = false;
|
||||||
} else {
|
} else {
|
||||||
saveLedState();
|
saveLedState();
|
||||||
}
|
}
|
||||||
preferences.putBool("ledStatus", ledStatus);
|
preferences.putBool("ledStatus", ledStatus);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveLedState() {
|
void saveLedState() {
|
||||||
for (int i = 0; i < pixels.numPixels(); i++)
|
for (int i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
|
||||||
int pixelColor = pixels.getPixelColor(i);
|
int pixelColor = pixels.getPixelColor(i);
|
||||||
char key[12];
|
char key[12];
|
||||||
snprintf(key, 12, "%s%d", "ledColor_", i);
|
snprintf(key, 12, "%s%d", "ledColor_", i);
|
||||||
|
@ -281,8 +246,7 @@ void saveLedState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreLedState() {
|
void restoreLedState() {
|
||||||
for (int i = 0; i < pixels.numPixels(); i++)
|
for (int i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
|
||||||
char key[12];
|
char key[12];
|
||||||
snprintf(key, 12, "%s%d", "ledColor_", i);
|
snprintf(key, 12, "%s%d", "ledColor_", i);
|
||||||
uint pixelColor = preferences.getUInt(key, pixels.Color(0, 0, 0));
|
uint pixelColor = preferences.getUInt(key, pixels.Color(0, 0, 0));
|
||||||
|
@ -292,15 +256,10 @@ void restoreLedState() {
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueHandle_t getLedTaskQueue()
|
QueueHandle_t getLedTaskQueue() { return ledTaskQueue; }
|
||||||
{
|
|
||||||
return ledTaskQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool queueLedEffect(uint effect)
|
bool queueLedEffect(uint effect) {
|
||||||
{
|
if (ledTaskQueue == NULL) {
|
||||||
if (ledTaskQueue == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,14 +267,13 @@ bool queueLedEffect(uint effect)
|
||||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledRainbow(int wait)
|
void ledRainbow(int wait) {
|
||||||
{
|
|
||||||
// Hue of first pixel runs 5 complete loops through the color wheel.
|
// Hue of first pixel runs 5 complete loops through the color wheel.
|
||||||
// Color wheel has a range of 65536 but it's OK if we roll over, so
|
// Color wheel has a range of 65536 but it's OK if we roll over, so
|
||||||
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
|
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
|
||||||
// means we'll make 5*65536/256 = 1280 passes through this loop:
|
// means we'll make 5*65536/256 = 1280 passes through this loop:
|
||||||
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256)
|
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536;
|
||||||
{
|
firstPixelHue += 256) {
|
||||||
// strip.rainbow() can take a single argument (first pixel hue) or
|
// strip.rainbow() can take a single argument (first pixel hue) or
|
||||||
// optionally a few extras: number of rainbow repetitions (default 1),
|
// optionally a few extras: number of rainbow repetitions (default 1),
|
||||||
// saturation and value (brightness) (both 0-255, similar to the
|
// saturation and value (brightness) (both 0-255, similar to the
|
||||||
|
@ -330,16 +288,12 @@ void ledRainbow(int wait)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledTheaterChase(uint32_t color, int wait)
|
void ledTheaterChase(uint32_t color, int wait) {
|
||||||
{
|
for (int a = 0; a < 10; a++) { // Repeat 10 times...
|
||||||
for (int a = 0; a < 10; a++)
|
for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2...
|
||||||
{ // Repeat 10 times...
|
|
||||||
for (int b = 0; b < 3; b++)
|
|
||||||
{ // 'b' counts from 0 to 2...
|
|
||||||
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
||||||
// 'c' counts up from 'b' to end of strip in steps of 3...
|
// 'c' counts up from 'b' to end of strip in steps of 3...
|
||||||
for (int c = b; c < pixels.numPixels(); c += 3)
|
for (int c = b; c < pixels.numPixels(); c += 3) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
||||||
}
|
}
|
||||||
pixels.show(); // Update strip with new contents
|
pixels.show(); // Update strip with new contents
|
||||||
|
@ -348,17 +302,13 @@ void ledTheaterChase(uint32_t color, int wait)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledTheaterChaseRainbow(int wait)
|
void ledTheaterChaseRainbow(int wait) {
|
||||||
{
|
|
||||||
int firstPixelHue = 0; // First pixel starts at red (hue 0)
|
int firstPixelHue = 0; // First pixel starts at red (hue 0)
|
||||||
for (int a = 0; a < 30; a++)
|
for (int a = 0; a < 30; a++) { // Repeat 30 times...
|
||||||
{ // Repeat 30 times...
|
for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2...
|
||||||
for (int b = 0; b < 3; b++)
|
|
||||||
{ // 'b' counts from 0 to 2...
|
|
||||||
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
||||||
// 'c' counts up from 'b' to end of strip in increments of 3...
|
// 'c' counts up from 'b' to end of strip in increments of 3...
|
||||||
for (int c = b; c < pixels.numPixels(); c += 3)
|
for (int c = b; c < pixels.numPixels(); c += 3) {
|
||||||
{
|
|
||||||
// hue of pixel 'c' is offset by an amount to make one full
|
// hue of pixel 'c' is offset by an amount to make one full
|
||||||
// revolution of the color wheel (range 65536) along the length
|
// revolution of the color wheel (range 65536) along the length
|
||||||
// of the strip (strip.numPixels() steps):
|
// of the strip (strip.numPixels() steps):
|
||||||
|
@ -373,7 +323,4 @@ void ledTheaterChaseRainbow(int wait)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Adafruit_NeoPixel getPixels()
|
Adafruit_NeoPixel getPixels() { return pixels; }
|
||||||
{
|
|
||||||
return pixels;
|
|
||||||
}
|
|
|
@ -1,11 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include "lib/shared.hpp"
|
||||||
|
#include "lib/webserver.hpp"
|
||||||
#include <Adafruit_NeoPixel.h>
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
#include <Arduino.h>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include "webserver.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
#ifndef NEOPIXEL_PIN
|
#ifndef NEOPIXEL_PIN
|
||||||
#define NEOPIXEL_PIN 34
|
#define NEOPIXEL_PIN 34
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
TaskHandle_t taskOtaHandle = NULL;
|
TaskHandle_t taskOtaHandle = NULL;
|
||||||
|
|
||||||
void setupOTA()
|
void setupOTA() {
|
||||||
{
|
if (preferences.getBool("otaEnabled", true)) {
|
||||||
if (preferences.getBool("otaEnabled", true))
|
|
||||||
{
|
|
||||||
ArduinoOTA.onStart(onOTAStart);
|
ArduinoOTA.onStart(onOTAStart);
|
||||||
|
|
||||||
ArduinoOTA.onProgress(onOTAProgress);
|
ArduinoOTA.onProgress(onOTAProgress);
|
||||||
|
@ -18,37 +16,33 @@ void setupOTA()
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
// downloadUpdate();
|
// downloadUpdate();
|
||||||
|
|
||||||
xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY, &taskOtaHandle);
|
xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&taskOtaHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAProgress(unsigned int progress, unsigned int total)
|
void onOTAProgress(unsigned int progress, unsigned int total) {
|
||||||
{
|
|
||||||
uint percentage = progress / (total / 100);
|
uint percentage = progress / (total / 100);
|
||||||
pixels.fill(pixels.Color(0, 255, 0));
|
pixels.fill(pixels.Color(0, 255, 0));
|
||||||
if (percentage < 100)
|
if (percentage < 100) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 75)
|
if (percentage < 75) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(1, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 50)
|
if (percentage < 50) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(2, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(2, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 25)
|
if (percentage < 25) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(3, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(3, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAStart()
|
void onOTAStart() {
|
||||||
{
|
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
std::array<String, NUM_SCREENS> epdContent = {"U", "P", "D", "A", "T", "E", "!"};
|
std::array<String, NUM_SCREENS> epdContent = {"U", "P", "D", "A",
|
||||||
|
"T", "E", "!"};
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
// Stop all timers
|
// Stop all timers
|
||||||
esp_timer_stop(screenRotateTimer);
|
esp_timer_stop(screenRotateTimer);
|
||||||
|
@ -68,17 +62,14 @@ void onOTAStart()
|
||||||
stopPriceNotify();
|
stopPriceNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleOTATask(void *parameter)
|
void handleOTATask(void *parameter) {
|
||||||
{
|
for (;;) {
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ArduinoOTA.handle(); // Allow OTA updates to occur
|
ArduinoOTA.handle(); // Allow OTA updates to occur
|
||||||
vTaskDelay(pdMS_TO_TICKS(2500));
|
vTaskDelay(pdMS_TO_TICKS(2500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void downloadUpdate()
|
void downloadUpdate() {
|
||||||
{
|
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
|
@ -87,11 +78,11 @@ void downloadUpdate()
|
||||||
// Send HTTP request to CoinGecko API
|
// Send HTTP request to CoinGecko API
|
||||||
http.useHTTP10(true);
|
http.useHTTP10(true);
|
||||||
|
|
||||||
http.begin(client, "https://api.github.com/repos/btclock/btclock_v3/releases/latest");
|
http.begin(client,
|
||||||
|
"https://api.github.com/repos/btclock/btclock_v3/releases/latest");
|
||||||
int httpCode = http.GET();
|
int httpCode = http.GET();
|
||||||
|
|
||||||
if (httpCode == 200)
|
if (httpCode == 200) {
|
||||||
{
|
|
||||||
// WiFiClient * stream = http->getStreamPtr();
|
// WiFiClient * stream = http->getStreamPtr();
|
||||||
|
|
||||||
StaticJsonDocument<64> filter;
|
StaticJsonDocument<64> filter;
|
||||||
|
@ -102,18 +93,17 @@ void downloadUpdate()
|
||||||
|
|
||||||
SpiRamJsonDocument doc(1536);
|
SpiRamJsonDocument doc(1536);
|
||||||
|
|
||||||
DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter));
|
DeserializationError error = deserializeJson(
|
||||||
|
doc, http.getStream(), DeserializationOption::Filter(filter));
|
||||||
|
|
||||||
if (error)
|
if (error) {
|
||||||
{
|
|
||||||
Serial.print("deserializeJson() failed: ");
|
Serial.print("deserializeJson() failed: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String downloadUrl;
|
String downloadUrl;
|
||||||
for (JsonObject asset : doc["assets"].as<JsonArray>())
|
for (JsonObject asset : doc["assets"].as<JsonArray>()) {
|
||||||
{
|
|
||||||
if (asset["name"].as<String>().compareTo("firmware.bin") == 0) {
|
if (asset["name"].as<String>().compareTo("firmware.bin") == 0) {
|
||||||
downloadUrl = asset["browser_download_url"].as<String>();
|
downloadUrl = asset["browser_download_url"].as<String>();
|
||||||
break;
|
break;
|
||||||
|
@ -122,8 +112,6 @@ void downloadUpdate()
|
||||||
|
|
||||||
Serial.printf("Download update from %s", downloadUrl);
|
Serial.printf("Download update from %s", downloadUrl);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// esp_http_client_config_t config = {
|
// esp_http_client_config_t config = {
|
||||||
// .url = CONFIG_FIRMWARE_UPGRADE_URL,
|
// .url = CONFIG_FIRMWARE_UPGRADE_URL,
|
||||||
// };
|
// };
|
||||||
|
@ -138,8 +126,7 @@ void downloadUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAError(ota_error_t error)
|
void onOTAError(ota_error_t error) {
|
||||||
{
|
|
||||||
Serial.println("\nOTA update error, restarting");
|
Serial.println("\nOTA update error, restarting");
|
||||||
Wire.end();
|
Wire.end();
|
||||||
SPI.end();
|
SPI.end();
|
||||||
|
@ -147,8 +134,7 @@ void onOTAError(ota_error_t error)
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAComplete()
|
void onOTAComplete() {
|
||||||
{
|
|
||||||
Serial.println("\nOTA update finished");
|
Serial.println("\nOTA update finished");
|
||||||
Wire.end();
|
Wire.end();
|
||||||
SPI.end();
|
SPI.end();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include "config.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
void setupOTA();
|
void setupOTA();
|
||||||
void onOTAStart();
|
void onOTAStart();
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
#include "price_fetch.hpp"
|
#include "price_fetch.hpp"
|
||||||
|
|
||||||
const PROGMEM char *cgApiUrl = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd%2Ceur";
|
const PROGMEM char *cgApiUrl = "https://api.coingecko.com/api/v3/simple/"
|
||||||
|
"price?ids=bitcoin&vs_currencies=usd%2Ceur";
|
||||||
|
|
||||||
TaskHandle_t priceFetchTaskHandle;
|
TaskHandle_t priceFetchTaskHandle;
|
||||||
|
|
||||||
void taskPriceFetch(void *pvParameters)
|
void taskPriceFetch(void *pvParameters) {
|
||||||
{
|
|
||||||
WiFiClientSecure *client = new WiFiClientSecure;
|
WiFiClientSecure *client = new WiFiClientSecure;
|
||||||
client->setInsecure();
|
client->setInsecure();
|
||||||
for (;;)
|
for (;;) {
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
HTTPClient *http = new HTTPClient();
|
HTTPClient *http = new HTTPClient();
|
||||||
|
@ -22,8 +21,7 @@ void taskPriceFetch(void *pvParameters)
|
||||||
|
|
||||||
// Parse JSON response and extract average price
|
// Parse JSON response and extract average price
|
||||||
uint usdPrice, eurPrice;
|
uint usdPrice, eurPrice;
|
||||||
if (httpCode == 200)
|
if (httpCode == 200) {
|
||||||
{
|
|
||||||
String payload = http->getString();
|
String payload = http->getString();
|
||||||
StaticJsonDocument<96> doc;
|
StaticJsonDocument<96> doc;
|
||||||
deserializeJson(doc, payload);
|
deserializeJson(doc, payload);
|
||||||
|
@ -31,30 +29,28 @@ void taskPriceFetch(void *pvParameters)
|
||||||
eurPrice = doc["bitcoin"]["eur"].as<uint>();
|
eurPrice = doc["bitcoin"]["eur"].as<uint>();
|
||||||
|
|
||||||
setPrice(eurPrice);
|
setPrice(eurPrice);
|
||||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP))
|
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||||
{
|
getCurrentScreen() == SCREEN_MSCW_TIME ||
|
||||||
|
getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
preferences.putUInt("lastPrice", eurPrice);
|
preferences.putUInt("lastPrice", eurPrice);
|
||||||
}
|
} else {
|
||||||
else
|
Serial.print(
|
||||||
{
|
F("Error retrieving BTC/USD price (CoinGecko). HTTP status code: "));
|
||||||
Serial.print(F("Error retrieving BTC/USD price (CoinGecko). HTTP status code: "));
|
|
||||||
Serial.println(httpCode);
|
Serial.println(httpCode);
|
||||||
if (httpCode == -1)
|
if (httpCode == -1) {
|
||||||
{
|
|
||||||
WiFi.reconnect();
|
WiFi.reconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPriceFetchTask()
|
void setupPriceFetchTask() {
|
||||||
{
|
xTaskCreate(taskPriceFetch, "priceFetch", (6 * 1024), NULL, tskIDLE_PRIORITY,
|
||||||
xTaskCreate(taskPriceFetch, "priceFetch", (6*1024), NULL, tskIDLE_PRIORITY, &priceFetchTaskHandle);
|
&priceFetchTaskHandle);
|
||||||
|
|
||||||
xTaskNotifyGive(priceFetchTaskHandle);
|
xTaskNotifyGive(priceFetchTaskHandle);
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include "config.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
extern TaskHandle_t priceFetchTaskHandle;
|
extern TaskHandle_t priceFetchTaskHandle;
|
||||||
|
|
||||||
|
|
|
@ -38,28 +38,25 @@ esp_websocket_client_handle_t clientPrice = NULL;
|
||||||
uint currentPrice = 30000;
|
uint currentPrice = 30000;
|
||||||
unsigned long int lastPriceUpdate;
|
unsigned long int lastPriceUpdate;
|
||||||
|
|
||||||
void setupPriceNotify()
|
void setupPriceNotify() {
|
||||||
{
|
|
||||||
// currentPrice = preferences.get("lastPrice", 30000);
|
// currentPrice = preferences.get("lastPrice", 30000);
|
||||||
|
|
||||||
esp_websocket_client_config_t config = {
|
esp_websocket_client_config_t config = {.uri = wsServerPrice,
|
||||||
.uri = wsServerPrice,
|
|
||||||
// .task_stack = (7*1024),
|
// .task_stack = (7*1024),
|
||||||
// .cert_pem = coinCapWsCert,
|
// .cert_pem = coinCapWsCert,
|
||||||
.user_agent = USER_AGENT
|
.user_agent = USER_AGENT};
|
||||||
};
|
|
||||||
|
|
||||||
clientPrice = esp_websocket_client_init(&config);
|
clientPrice = esp_websocket_client_init(&config);
|
||||||
esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY, onWebsocketPriceEvent, clientPrice);
|
esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY,
|
||||||
|
onWebsocketPriceEvent, clientPrice);
|
||||||
esp_websocket_client_start(clientPrice);
|
esp_websocket_client_start(clientPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
|
||||||
{
|
int32_t event_id, void *event_data) {
|
||||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||||
|
|
||||||
switch (event_id)
|
switch (event_id) {
|
||||||
{
|
|
||||||
case WEBSOCKET_EVENT_CONNECTED:
|
case WEBSOCKET_EVENT_CONNECTED:
|
||||||
Serial.println(F("Connected to CoinCap.io WebSocket"));
|
Serial.println(F("Connected to CoinCap.io WebSocket"));
|
||||||
break;
|
break;
|
||||||
|
@ -75,8 +72,7 @@ void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t ev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
|
||||||
{
|
|
||||||
SpiRamJsonDocument doc(event_data->data_len);
|
SpiRamJsonDocument doc(event_data->data_len);
|
||||||
|
|
||||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||||
|
@ -84,16 +80,20 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
||||||
if (doc.containsKey("bitcoin")) {
|
if (doc.containsKey("bitcoin")) {
|
||||||
if (currentPrice != doc["bitcoin"].as<long>()) {
|
if (currentPrice != doc["bitcoin"].as<long>()) {
|
||||||
|
|
||||||
uint minSecPriceUpd = preferences.getUInt("minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
uint minSecPriceUpd = preferences.getUInt(
|
||||||
|
"minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
||||||
uint currentTime = esp_timer_get_time() / 1000000;
|
uint currentTime = esp_timer_get_time() / 1000000;
|
||||||
|
|
||||||
if (lastPriceUpdate == 0 || (currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
if (lastPriceUpdate == 0 ||
|
||||||
|
(currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
||||||
// const unsigned long oldPrice = currentPrice;
|
// const unsigned long oldPrice = currentPrice;
|
||||||
currentPrice = doc["bitcoin"].as<uint>();
|
currentPrice = doc["bitcoin"].as<uint>();
|
||||||
preferences.putUInt("lastPrice", currentPrice);
|
preferences.putUInt("lastPrice", currentPrice);
|
||||||
lastPriceUpdate = currentTime;
|
lastPriceUpdate = currentTime;
|
||||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||||
|
getCurrentScreen() == SCREEN_MSCW_TIME ||
|
||||||
|
getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
@ -103,13 +103,9 @@ void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getPrice() {
|
uint getPrice() { return currentPrice; }
|
||||||
return currentPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPrice(uint newPrice) {
|
void setPrice(uint newPrice) { currentPrice = newPrice; }
|
||||||
currentPrice = newPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPriceNotifyConnected() {
|
bool isPriceNotifyConnected() {
|
||||||
if (clientPrice == NULL)
|
if (clientPrice == NULL)
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "esp_websocket_client.h"
|
#include <esp_websocket_client.h>
|
||||||
#include "screen_handler.hpp"
|
#include "lib/screen_handler.hpp"
|
||||||
|
|
||||||
// using namespace websockets;
|
// using namespace websockets;
|
||||||
|
|
||||||
void setupPriceNotify();
|
void setupPriceNotify();
|
||||||
|
|
||||||
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
|
||||||
|
int32_t event_id, void *event_data);
|
||||||
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data);
|
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data);
|
||||||
|
|
||||||
uint getPrice();
|
uint getPrice();
|
||||||
|
|
|
@ -8,7 +8,8 @@ TaskHandle_t workerTaskHandle;
|
||||||
esp_timer_handle_t screenRotateTimer;
|
esp_timer_handle_t screenRotateTimer;
|
||||||
esp_timer_handle_t minuteTimer;
|
esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> taskEpdContent = {"", "", "", "", "", "", ""};
|
std::array<std::string, NUM_SCREENS> taskEpdContent = {"", "", "", "",
|
||||||
|
"", "", ""};
|
||||||
std::string priceString;
|
std::string priceString;
|
||||||
|
|
||||||
// typedef enum
|
// typedef enum
|
||||||
|
@ -29,65 +30,50 @@ QueueHandle_t workQueue = NULL;
|
||||||
|
|
||||||
uint currentScreen;
|
uint currentScreen;
|
||||||
|
|
||||||
void workerTask(void *pvParameters)
|
void workerTask(void *pvParameters) {
|
||||||
{
|
|
||||||
WorkItem receivedItem;
|
WorkItem receivedItem;
|
||||||
|
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
// Wait for a work item to be available in the queue
|
// Wait for a work item to be available in the queue
|
||||||
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY))
|
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) {
|
||||||
{
|
|
||||||
uint firstIndex = 0;
|
uint firstIndex = 0;
|
||||||
|
|
||||||
// Process the work item based on its type
|
// Process the work item based on its type
|
||||||
switch (receivedItem.type)
|
switch (receivedItem.type) {
|
||||||
{
|
case TASK_PRICE_UPDATE: {
|
||||||
case TASK_PRICE_UPDATE:
|
|
||||||
{
|
|
||||||
uint price = getPrice();
|
uint price = getPrice();
|
||||||
char priceSymbol = '$';
|
char priceSymbol = '$';
|
||||||
if (preferences.getBool("fetchEurPrice", false))
|
if (preferences.getBool("fetchEurPrice", false)) {
|
||||||
{
|
|
||||||
priceSymbol = '[';
|
priceSymbol = '[';
|
||||||
}
|
}
|
||||||
if (getCurrentScreen() == SCREEN_BTC_TICKER)
|
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
||||||
{
|
|
||||||
taskEpdContent = parsePriceData(price, priceSymbol);
|
taskEpdContent = parsePriceData(price, priceSymbol);
|
||||||
}
|
} else if (getCurrentScreen() == SCREEN_MSCW_TIME) {
|
||||||
else if (getCurrentScreen() == SCREEN_MSCW_TIME)
|
|
||||||
{
|
|
||||||
taskEpdContent = parseSatsPerCurrency(price, priceSymbol);
|
taskEpdContent = parseSatsPerCurrency(price, priceSymbol);
|
||||||
}
|
} else {
|
||||||
else
|
taskEpdContent =
|
||||||
{
|
parseMarketCap(getBlockHeight(), price, priceSymbol,
|
||||||
taskEpdContent = parseMarketCap(getBlockHeight(), price, priceSymbol, preferences.getBool("mcapBigChar", true));
|
preferences.getBool("mcapBigChar", true));
|
||||||
}
|
}
|
||||||
|
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TASK_BLOCK_UPDATE:
|
case TASK_BLOCK_UPDATE: {
|
||||||
{
|
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
||||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN)
|
|
||||||
{
|
|
||||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
taskEpdContent = parseHalvingCountdown(getBlockHeight());
|
taskEpdContent = parseHalvingCountdown(getBlockHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN || getCurrentScreen() == SCREEN_BLOCK_HEIGHT)
|
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
||||||
{
|
getCurrentScreen() == SCREEN_BLOCK_HEIGHT) {
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TASK_TIME_UPDATE:
|
case TASK_TIME_UPDATE: {
|
||||||
{
|
if (getCurrentScreen() == SCREEN_TIME) {
|
||||||
if (getCurrentScreen() == SCREEN_TIME)
|
|
||||||
{
|
|
||||||
time_t currentTime;
|
time_t currentTime;
|
||||||
struct tm timeinfo;
|
struct tm timeinfo;
|
||||||
time(¤tTime);
|
time(¤tTime);
|
||||||
|
@ -95,17 +81,17 @@ void workerTask(void *pvParameters)
|
||||||
std::string timeString;
|
std::string timeString;
|
||||||
|
|
||||||
String minute = String(timeinfo.tm_min);
|
String minute = String(timeinfo.tm_min);
|
||||||
if (minute.length() < 2)
|
if (minute.length() < 2) {
|
||||||
{
|
|
||||||
minute = "0" + minute;
|
minute = "0" + minute;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeString = std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
timeString = std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
||||||
timeString.insert(timeString.begin(), NUM_SCREENS - timeString.length(), ' ');
|
timeString.insert(timeString.begin(),
|
||||||
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" + std::to_string(timeinfo.tm_mon + 1);
|
NUM_SCREENS - timeString.length(), ' ');
|
||||||
|
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" +
|
||||||
|
std::to_string(timeinfo.tm_mon + 1);
|
||||||
|
|
||||||
for (uint i = 1; i < NUM_SCREENS; i++)
|
for (uint i = 1; i < NUM_SCREENS; i++) {
|
||||||
{
|
|
||||||
taskEpdContent[i] = timeString[i];
|
taskEpdContent[i] = timeString[i];
|
||||||
}
|
}
|
||||||
setEpdContent(taskEpdContent);
|
setEpdContent(taskEpdContent);
|
||||||
|
@ -119,17 +105,14 @@ void workerTask(void *pvParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void taskScreenRotate(void *pvParameters)
|
void taskScreenRotate(void *pvParameters) {
|
||||||
{
|
for (;;) {
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
int nextScreen = (currentScreen + 1) % SCREEN_COUNT;
|
int nextScreen = (currentScreen + 1) % SCREEN_COUNT;
|
||||||
String key = "screen" + String(nextScreen) + "Visible";
|
String key = "screen" + String(nextScreen) + "Visible";
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
{
|
|
||||||
nextScreen = (nextScreen + 1) % SCREEN_COUNT;
|
nextScreen = (nextScreen + 1) % SCREEN_COUNT;
|
||||||
key = "screen" + String(nextScreen) + "Visible";
|
key = "screen" + String(nextScreen) + "Visible";
|
||||||
}
|
}
|
||||||
|
@ -138,52 +121,48 @@ void taskScreenRotate(void *pvParameters)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR minuteTimerISR(void *arg)
|
void IRAM_ATTR minuteTimerISR(void *arg) {
|
||||||
{
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
// vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
// vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
|
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
|
||||||
if (priceFetchTaskHandle != NULL)
|
if (priceFetchTaskHandle != NULL) {
|
||||||
{
|
|
||||||
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
|
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
{
|
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR screenRotateTimerISR(void *arg)
|
void IRAM_ATTR screenRotateTimerISR(void *arg) {
|
||||||
{
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken);
|
vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
{
|
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTasks()
|
void setupTasks() {
|
||||||
{
|
|
||||||
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
||||||
|
|
||||||
// xTaskCreate(taskPriceUpdate, "updatePrice", 1024, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
// xTaskCreate(taskPriceUpdate, "updatePrice", 1024, NULL, tskIDLE_PRIORITY,
|
||||||
// xTaskCreate(taskBlockUpdate, "updateBlock", 1024, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
// &priceUpdateTaskHandle); xTaskCreate(taskBlockUpdate, "updateBlock", 1024,
|
||||||
// xTaskCreate(taskTimeUpdate, "updateTime", 1024, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
// NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
||||||
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY, &workerTaskHandle);
|
// xTaskCreate(taskTimeUpdate, "updateTime", 1024, NULL, tskIDLE_PRIORITY,
|
||||||
|
// &timeUpdateTaskHandle);
|
||||||
|
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&workerTaskHandle);
|
||||||
|
|
||||||
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY,
|
||||||
|
&taskScreenRotateTaskHandle);
|
||||||
|
|
||||||
waitUntilNoneBusy();
|
waitUntilNoneBusy();
|
||||||
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimeUpdateTimer(void *pvParameters)
|
void setupTimeUpdateTimer(void *pvParameters) {
|
||||||
{
|
|
||||||
const esp_timer_create_args_t minuteTimerConfig = {
|
const esp_timer_create_args_t minuteTimerConfig = {
|
||||||
.callback = &minuteTimerISR,
|
.callback = &minuteTimerISR, .name = "minute_timer"};
|
||||||
.name = "minute_timer"};
|
|
||||||
|
|
||||||
esp_timer_create(&minuteTimerConfig, &minuteTimer);
|
esp_timer_create(&minuteTimerConfig, &minuteTimer);
|
||||||
|
|
||||||
|
@ -205,42 +184,31 @@ void setupTimeUpdateTimer(void *pvParameters)
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupScreenRotateTimer(void *pvParameters)
|
void setupScreenRotateTimer(void *pvParameters) {
|
||||||
{
|
|
||||||
const esp_timer_create_args_t screenRotateTimerConfig = {
|
const esp_timer_create_args_t screenRotateTimerConfig = {
|
||||||
.callback = &screenRotateTimerISR,
|
.callback = &screenRotateTimerISR, .name = "screen_rotate_timer"};
|
||||||
.name = "screen_rotate_timer"};
|
|
||||||
|
|
||||||
esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer);
|
esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer);
|
||||||
|
|
||||||
if (preferences.getBool("timerActive", true))
|
if (preferences.getBool("timerActive", true)) {
|
||||||
{
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
getTimerSeconds() * usPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getTimerSeconds()
|
uint getTimerSeconds() { return preferences.getUInt("timerSeconds", 1800); }
|
||||||
{
|
|
||||||
return preferences.getUInt("timerSeconds", 1800);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTimerActive()
|
bool isTimerActive() { return esp_timer_is_active(screenRotateTimer); }
|
||||||
{
|
|
||||||
return esp_timer_is_active(screenRotateTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTimerActive(bool status)
|
void setTimerActive(bool status) {
|
||||||
{
|
if (status) {
|
||||||
if (status)
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
{
|
getTimerSeconds() * usPerSecond);
|
||||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
|
||||||
queueLedEffect(LED_EFFECT_START_TIMER);
|
queueLedEffect(LED_EFFECT_START_TIMER);
|
||||||
preferences.putBool("timerActive", true);
|
preferences.putBool("timerActive", true);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
esp_timer_stop(screenRotateTimer);
|
esp_timer_stop(screenRotateTimer);
|
||||||
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
||||||
preferences.putBool("timerActive", false);
|
preferences.putBool("timerActive", false);
|
||||||
|
@ -250,37 +218,26 @@ void setTimerActive(bool status)
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleTimerActive()
|
void toggleTimerActive() { setTimerActive(!isTimerActive()); }
|
||||||
{
|
|
||||||
setTimerActive(!isTimerActive());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint getCurrentScreen()
|
uint getCurrentScreen() { return currentScreen; }
|
||||||
{
|
|
||||||
return currentScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCurrentScreen(uint newScreen)
|
void setCurrentScreen(uint newScreen) {
|
||||||
{
|
if (newScreen != SCREEN_CUSTOM) {
|
||||||
if (newScreen != SCREEN_CUSTOM)
|
|
||||||
{
|
|
||||||
preferences.putUInt("currentScreen", newScreen);
|
preferences.putUInt("currentScreen", newScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentScreen = newScreen;
|
currentScreen = newScreen;
|
||||||
|
|
||||||
switch (currentScreen)
|
switch (currentScreen) {
|
||||||
{
|
case SCREEN_TIME: {
|
||||||
case SCREEN_TIME:
|
|
||||||
{
|
|
||||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||||
// xTaskNotifyGive(timeUpdateTaskHandle);
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCREEN_HALVING_COUNTDOWN:
|
case SCREEN_HALVING_COUNTDOWN:
|
||||||
case SCREEN_BLOCK_HEIGHT:
|
case SCREEN_BLOCK_HEIGHT: {
|
||||||
{
|
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
@ -288,8 +245,7 @@ void setCurrentScreen(uint newScreen)
|
||||||
}
|
}
|
||||||
case SCREEN_MARKET_CAP:
|
case SCREEN_MARKET_CAP:
|
||||||
case SCREEN_MSCW_TIME:
|
case SCREEN_MSCW_TIME:
|
||||||
case SCREEN_BTC_TICKER:
|
case SCREEN_BTC_TICKER: {
|
||||||
{
|
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
// xTaskNotifyGive(priceUpdateTaskHandle);
|
// xTaskNotifyGive(priceUpdateTaskHandle);
|
||||||
|
@ -301,36 +257,32 @@ void setCurrentScreen(uint newScreen)
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nextScreen()
|
void nextScreen() {
|
||||||
{
|
|
||||||
int newCurrentScreen = (getCurrentScreen() + 1) % SCREEN_COUNT;
|
int newCurrentScreen = (getCurrentScreen() + 1) % SCREEN_COUNT;
|
||||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
{
|
|
||||||
newCurrentScreen = (newCurrentScreen + 1) % SCREEN_COUNT;
|
newCurrentScreen = (newCurrentScreen + 1) % SCREEN_COUNT;
|
||||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
}
|
}
|
||||||
setCurrentScreen(newCurrentScreen);
|
setCurrentScreen(newCurrentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void previousScreen()
|
void previousScreen() {
|
||||||
{
|
|
||||||
|
|
||||||
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
||||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
{
|
|
||||||
newCurrentScreen = modulo(newCurrentScreen - 1, SCREEN_COUNT);
|
newCurrentScreen = modulo(newCurrentScreen - 1, SCREEN_COUNT);
|
||||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
}
|
}
|
||||||
setCurrentScreen(newCurrentScreen);
|
setCurrentScreen(newCurrentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showSystemStatusScreen()
|
void showSystemStatusScreen() {
|
||||||
{
|
std::array<String, NUM_SCREENS> sysStatusEpdContent = {"", "", "", "",
|
||||||
std::array<String, NUM_SCREENS> sysStatusEpdContent = {"", "", "", "", "", "", ""};
|
"", "", ""};
|
||||||
|
|
||||||
String ipAddr = WiFi.localIP().toString();
|
String ipAddr = WiFi.localIP().toString();
|
||||||
String subNet = WiFi.subnetMask().toString();
|
String subNet = WiFi.subnetMask().toString();
|
||||||
|
@ -339,9 +291,9 @@ void showSystemStatusScreen()
|
||||||
|
|
||||||
int ipAddrPos = 0;
|
int ipAddrPos = 0;
|
||||||
int subnetPos = 0;
|
int subnetPos = 0;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++) {
|
||||||
{
|
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) +
|
||||||
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) + "/" + subNet.substring(0, subNet.indexOf('.'));
|
"/" + subNet.substring(0, subNet.indexOf('.'));
|
||||||
ipAddrPos = ipAddr.indexOf('.') + 1;
|
ipAddrPos = ipAddr.indexOf('.') + 1;
|
||||||
subnetPos = subNet.indexOf('.') + 1;
|
subnetPos = subNet.indexOf('.') + 1;
|
||||||
ipAddr = ipAddr.substring(ipAddrPos);
|
ipAddr = ipAddr.substring(ipAddrPos);
|
||||||
|
@ -349,7 +301,9 @@ void showSystemStatusScreen()
|
||||||
}
|
}
|
||||||
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
||||||
|
|
||||||
sysStatusEpdContent[NUM_SCREENS - 1] = String((int)round(ESP.getFreeHeap() / 1024)) + "/" + (int)round(ESP.getHeapSize() / 1024);
|
sysStatusEpdContent[NUM_SCREENS - 1] =
|
||||||
|
String((int)round(ESP.getFreeHeap() / 1024)) + "/" +
|
||||||
|
(int)round(ESP.getHeapSize() / 1024);
|
||||||
setCurrentScreen(SCREEN_CUSTOM);
|
setCurrentScreen(SCREEN_CUSTOM);
|
||||||
setEpdContent(sysStatusEpdContent);
|
setEpdContent(sysStatusEpdContent);
|
||||||
}
|
}
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
#include <esp_timer.h>
|
#include <esp_timer.h>
|
||||||
|
|
||||||
|
#include <data_handler.hpp>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <data_handler.hpp>
|
|
||||||
|
|
||||||
#include "price_fetch.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
#include "lib/epd.hpp"
|
#include "lib/epd.hpp"
|
||||||
|
#include "lib/price_fetch.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
|
||||||
// extern TaskHandle_t priceUpdateTaskHandle;
|
// extern TaskHandle_t priceUpdateTaskHandle;
|
||||||
// extern TaskHandle_t blockUpdateTaskHandle;
|
// extern TaskHandle_t blockUpdateTaskHandle;
|
||||||
|
@ -21,15 +21,13 @@ extern esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
extern QueueHandle_t workQueue;
|
extern QueueHandle_t workQueue;
|
||||||
|
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
|
||||||
TASK_PRICE_UPDATE,
|
TASK_PRICE_UPDATE,
|
||||||
TASK_BLOCK_UPDATE,
|
TASK_BLOCK_UPDATE,
|
||||||
TASK_TIME_UPDATE
|
TASK_TIME_UPDATE
|
||||||
} TaskType;
|
} TaskType;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
TaskType type;
|
TaskType type;
|
||||||
char data;
|
char data;
|
||||||
} WorkItem;
|
} WorkItem;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
#include <freertos/task.h>
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include <Adafruit_MCP23X17.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include <utils.hpp>
|
||||||
|
|
||||||
extern Adafruit_MCP23X17 mcp1;
|
extern Adafruit_MCP23X17 mcp1;
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
|
@ -26,7 +26,9 @@ const PROGMEM int SCREEN_MARKET_CAP = 5;
|
||||||
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
||||||
const PROGMEM int SCREEN_CUSTOM = 99;
|
const PROGMEM int SCREEN_CUSTOM = 99;
|
||||||
const int SCREEN_COUNT = 6;
|
const int SCREEN_COUNT = 6;
|
||||||
const PROGMEM int screens[SCREEN_COUNT] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP };
|
const PROGMEM int screens[SCREEN_COUNT] = {
|
||||||
|
SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER,
|
||||||
|
SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP};
|
||||||
const int usPerSecond = 1000000;
|
const int usPerSecond = 1000000;
|
||||||
const int usPerMinute = 60 * usPerSecond;
|
const int usPerMinute = 60 * usPerSecond;
|
||||||
|
|
||||||
|
@ -35,9 +37,7 @@ struct SpiRamAllocator {
|
||||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* pointer) {
|
void deallocate(void *pointer) { heap_caps_free(pointer); }
|
||||||
heap_caps_free(pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *reallocate(void *ptr, size_t new_size) {
|
void *reallocate(void *ptr, size_t new_size) {
|
||||||
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||||
|
@ -45,4 +45,3 @@ struct SpiRamAllocator {
|
||||||
};
|
};
|
||||||
|
|
||||||
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ AsyncWebServer server(80);
|
||||||
AsyncEventSource events("/events");
|
AsyncEventSource events("/events");
|
||||||
TaskHandle_t eventSourceTaskHandle;
|
TaskHandle_t eventSourceTaskHandle;
|
||||||
|
|
||||||
void setupWebserver()
|
void setupWebserver() {
|
||||||
{
|
|
||||||
|
|
||||||
events.onConnect([](AsyncEventSourceClient *client)
|
events.onConnect([](AsyncEventSourceClient *client) {
|
||||||
{ client->send("welcome", NULL, millis(), 1000); });
|
client->send("welcome", NULL, millis(), 1000);
|
||||||
|
});
|
||||||
server.addHandler(&events);
|
server.addHandler(&events);
|
||||||
|
|
||||||
// server.serveStatic("/css", LittleFS, "/css/");
|
// server.serveStatic("/css", LittleFS, "/css/");
|
||||||
|
@ -34,42 +34,48 @@ void setupWebserver()
|
||||||
server.on("/api/show/screen", HTTP_GET, onApiShowScreen);
|
server.on("/api/show/screen", HTTP_GET, onApiShowScreen);
|
||||||
server.on("/api/show/text", HTTP_GET, onApiShowText);
|
server.on("/api/show/text", HTTP_GET, onApiShowText);
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler *settingsPatchHandler = new AsyncCallbackJsonWebHandler("/api/json/settings", onApiSettingsPatch);
|
AsyncCallbackJsonWebHandler *settingsPatchHandler =
|
||||||
|
new AsyncCallbackJsonWebHandler("/api/json/settings", onApiSettingsPatch);
|
||||||
server.addHandler(settingsPatchHandler);
|
server.addHandler(settingsPatchHandler);
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler("/api/show/custom", onApiShowTextAdvanced);
|
AsyncCallbackJsonWebHandler *handler = new AsyncCallbackJsonWebHandler(
|
||||||
|
"/api/show/custom", onApiShowTextAdvanced);
|
||||||
server.addHandler(handler);
|
server.addHandler(handler);
|
||||||
|
|
||||||
AsyncCallbackJsonWebHandler *lightsJsonHandler = new AsyncCallbackJsonWebHandler("/api/lights", onApiLightsSetJson);
|
AsyncCallbackJsonWebHandler *lightsJsonHandler =
|
||||||
|
new AsyncCallbackJsonWebHandler("/api/lights", onApiLightsSetJson);
|
||||||
server.addHandler(lightsJsonHandler);
|
server.addHandler(lightsJsonHandler);
|
||||||
|
|
||||||
server.on("/api/lights/off", HTTP_GET, onApiLightsOff);
|
server.on("/api/lights/off", HTTP_GET, onApiLightsOff);
|
||||||
server.on("/api/lights/color", HTTP_GET, onApiLightsSetColor);
|
server.on("/api/lights/color", HTTP_GET, onApiLightsSetColor);
|
||||||
server.on("/api/lights", HTTP_GET, onApiLightsStatus);
|
server.on("/api/lights", HTTP_GET, onApiLightsStatus);
|
||||||
|
|
||||||
// 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.on("/api/restart", HTTP_GET, onApiRestart);
|
||||||
server.addRewrite(new OneParamRewrite("/api/lights/{color}", "/api/lights/color?c={color}"));
|
server.addRewrite(new OneParamRewrite("/api/lights/{color}",
|
||||||
server.addRewrite(new OneParamRewrite("/api/show/screen/{s}", "/api/show/screen?s={s}"));
|
"/api/lights/color?c={color}"));
|
||||||
server.addRewrite(new OneParamRewrite("/api/show/text/{text}", "/api/show/text?t={text}"));
|
server.addRewrite(
|
||||||
server.addRewrite(new OneParamRewrite("/api/show/number/{number}", "/api/show/text?t={text}"));
|
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);
|
server.onNotFound(onNotFound);
|
||||||
|
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods", "GET, PATCH, POST, OPTIONS");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods",
|
||||||
|
"GET, PATCH, POST, OPTIONS");
|
||||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*");
|
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "*");
|
||||||
|
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|
||||||
if (preferences.getBool("mdnsEnabled", true))
|
if (preferences.getBool("mdnsEnabled", true)) {
|
||||||
{
|
if (!MDNS.begin(getMyHostname())) {
|
||||||
if (!MDNS.begin(getMyHostname()))
|
|
||||||
{
|
|
||||||
Serial.println(F("Error setting up MDNS responder!"));
|
Serial.println(F("Error setting up MDNS responder!"));
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
|
||||||
delay(1000);
|
delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,16 +85,13 @@ void setupWebserver()
|
||||||
MDNS.addServiceTxt("http", "tcp", "rev", GIT_REV);
|
MDNS.addServiceTxt("http", "tcp", "rev", GIT_REV);
|
||||||
}
|
}
|
||||||
|
|
||||||
xTaskCreate(eventSourceTask, "eventSourceTask", 4096, NULL, tskIDLE_PRIORITY, &eventSourceTaskHandle);
|
xTaskCreate(eventSourceTask, "eventSourceTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopWebServer()
|
void stopWebServer() { server.end(); }
|
||||||
{
|
|
||||||
server.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
StaticJsonDocument<768> getStatusObject()
|
StaticJsonDocument<768> getStatusObject() {
|
||||||
{
|
|
||||||
StaticJsonDocument<768> root;
|
StaticJsonDocument<768> root;
|
||||||
|
|
||||||
root["currentScreen"] = getCurrentScreen();
|
root["currentScreen"] = getCurrentScreen();
|
||||||
|
@ -111,14 +114,12 @@ StaticJsonDocument<768> getStatusObject()
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticJsonDocument<512> getLedStatusObject()
|
StaticJsonDocument<512> getLedStatusObject() {
|
||||||
{
|
|
||||||
StaticJsonDocument<512> root;
|
StaticJsonDocument<512> root;
|
||||||
JsonArray colors = root.createNestedArray("data");
|
JsonArray colors = root.createNestedArray("data");
|
||||||
// Adafruit_NeoPixel pix = getPixels();
|
// Adafruit_NeoPixel pix = getPixels();
|
||||||
|
|
||||||
for (uint i = 0; i < pixels.numPixels(); i++)
|
for (uint i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
|
||||||
uint32_t pixColor = pixels.getPixelColor(pixels.numPixels() - i - 1);
|
uint32_t pixColor = pixels.getPixelColor(pixels.numPixels() - i - 1);
|
||||||
uint alpha = (pixColor >> 24) & 0xFF;
|
uint alpha = (pixColor >> 24) & 0xFF;
|
||||||
uint red = (pixColor >> 16) & 0xFF;
|
uint red = (pixColor >> 16) & 0xFF;
|
||||||
|
@ -137,8 +138,7 @@ StaticJsonDocument<512> getLedStatusObject()
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eventSourceUpdate()
|
void eventSourceUpdate() {
|
||||||
{
|
|
||||||
if (!events.count())
|
if (!events.count())
|
||||||
return;
|
return;
|
||||||
StaticJsonDocument<768> root = getStatusObject();
|
StaticJsonDocument<768> root = getStatusObject();
|
||||||
|
@ -162,9 +162,9 @@ void eventSourceUpdate()
|
||||||
* @Api
|
* @Api
|
||||||
* @Path("/api/status")
|
* @Path("/api/status")
|
||||||
*/
|
*/
|
||||||
void onApiStatus(AsyncWebServerRequest *request)
|
void onApiStatus(AsyncWebServerRequest *request) {
|
||||||
{
|
AsyncResponseStream *response =
|
||||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
request->beginResponseStream("application/json");
|
||||||
|
|
||||||
StaticJsonDocument<1024> root = getStatusObject();
|
StaticJsonDocument<1024> root = getStatusObject();
|
||||||
JsonArray data = root.createNestedArray("data");
|
JsonArray data = root.createNestedArray("data");
|
||||||
|
@ -188,8 +188,7 @@ void onApiStatus(AsyncWebServerRequest *request)
|
||||||
* @Api
|
* @Api
|
||||||
* @Path("/api/action/pause")
|
* @Path("/api/action/pause")
|
||||||
*/
|
*/
|
||||||
void onApiActionPause(AsyncWebServerRequest *request)
|
void onApiActionPause(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
setTimerActive(false);
|
setTimerActive(false);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
};
|
};
|
||||||
|
@ -198,8 +197,7 @@ void onApiActionPause(AsyncWebServerRequest *request)
|
||||||
* @Api
|
* @Api
|
||||||
* @Path("/api/action/timer_restart")
|
* @Path("/api/action/timer_restart")
|
||||||
*/
|
*/
|
||||||
void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
void onApiActionTimerRestart(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
setTimerActive(true);
|
setTimerActive(true);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
@ -208,8 +206,7 @@ void onApiActionTimerRestart(AsyncWebServerRequest *request)
|
||||||
* @Api
|
* @Api
|
||||||
* @Path("/api/full_refresh")
|
* @Path("/api/full_refresh")
|
||||||
*/
|
*/
|
||||||
void onApiFullRefresh(AsyncWebServerRequest *request)
|
void onApiFullRefresh(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
std::array<String, NUM_SCREENS> newEpdContent = getCurrentEpdContent();
|
std::array<String, NUM_SCREENS> newEpdContent = getCurrentEpdContent();
|
||||||
|
|
||||||
|
@ -222,10 +219,8 @@ void onApiFullRefresh(AsyncWebServerRequest *request)
|
||||||
* @Api
|
* @Api
|
||||||
* @Path("/api/show/screen")
|
* @Path("/api/show/screen")
|
||||||
*/
|
*/
|
||||||
void onApiShowScreen(AsyncWebServerRequest *request)
|
void onApiShowScreen(AsyncWebServerRequest *request) {
|
||||||
{
|
if (request->hasParam("s")) {
|
||||||
if (request->hasParam("s"))
|
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam("s");
|
AsyncWebParameter *p = request->getParam("s");
|
||||||
uint currentScreen = p->value().toInt();
|
uint currentScreen = p->value().toInt();
|
||||||
setCurrentScreen(currentScreen);
|
setCurrentScreen(currentScreen);
|
||||||
|
@ -233,17 +228,14 @@ void onApiShowScreen(AsyncWebServerRequest *request)
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiShowText(AsyncWebServerRequest *request)
|
void onApiShowText(AsyncWebServerRequest *request) {
|
||||||
{
|
if (request->hasParam("t")) {
|
||||||
if (request->hasParam("t"))
|
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam("t");
|
AsyncWebParameter *p = request->getParam("t");
|
||||||
String t = p->value();
|
String t = p->value();
|
||||||
t.toUpperCase(); // This is needed as long as lowercase letters are glitchy
|
t.toUpperCase(); // This is needed as long as lowercase letters are glitchy
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> textEpdContent;
|
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];
|
textEpdContent[i] = t[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,14 +245,12 @@ void onApiShowText(AsyncWebServerRequest *request)
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiShowTextAdvanced(AsyncWebServerRequest *request, JsonVariant &json)
|
void onApiShowTextAdvanced(AsyncWebServerRequest *request, JsonVariant &json) {
|
||||||
{
|
|
||||||
JsonArray screens = json.as<JsonArray>();
|
JsonArray screens = json.as<JsonArray>();
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> epdContent;
|
std::array<String, NUM_SCREENS> epdContent;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (JsonVariant s : screens)
|
for (JsonVariant s : screens) {
|
||||||
{
|
|
||||||
epdContent[i] = s.as<String>();
|
epdContent[i] = s.as<String>();
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -271,14 +261,12 @@ void onApiShowTextAdvanced(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) {
|
||||||
{
|
|
||||||
JsonObject settings = json.as<JsonObject>();
|
JsonObject settings = json.as<JsonObject>();
|
||||||
|
|
||||||
bool settingsChanged = true;
|
bool settingsChanged = true;
|
||||||
|
|
||||||
if (settings.containsKey("fgColor"))
|
if (settings.containsKey("fgColor")) {
|
||||||
{
|
|
||||||
String fgColor = settings["fgColor"].as<String>();
|
String fgColor = settings["fgColor"].as<String>();
|
||||||
preferences.putUInt("fgColor", strtol(fgColor.c_str(), NULL, 16));
|
preferences.putUInt("fgColor", strtol(fgColor.c_str(), NULL, 16));
|
||||||
setFgColor(int(strtol(fgColor.c_str(), NULL, 16)));
|
setFgColor(int(strtol(fgColor.c_str(), NULL, 16)));
|
||||||
|
@ -286,8 +274,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
Serial.println(strtol(fgColor.c_str(), NULL, 16));
|
Serial.println(strtol(fgColor.c_str(), NULL, 16));
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
if (settings.containsKey("bgColor"))
|
if (settings.containsKey("bgColor")) {
|
||||||
{
|
|
||||||
String bgColor = settings["bgColor"].as<String>();
|
String bgColor = settings["bgColor"].as<String>();
|
||||||
|
|
||||||
preferences.putUInt("bgColor", strtol(bgColor.c_str(), NULL, 16));
|
preferences.putUInt("bgColor", strtol(bgColor.c_str(), NULL, 16));
|
||||||
|
@ -297,56 +284,52 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.containsKey("timePerScreen"))
|
if (settings.containsKey("timePerScreen")) {
|
||||||
{
|
preferences.putUInt("timerSeconds",
|
||||||
preferences.putUInt("timerSeconds", settings["timePerScreen"].as<uint>() * 60);
|
settings["timePerScreen"].as<uint>() * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
String strSettings[] = {"hostnamePrefix", "mempoolInstance"};
|
String strSettings[] = {"hostnamePrefix", "mempoolInstance"};
|
||||||
|
|
||||||
for (String setting : strSettings)
|
for (String setting : strSettings) {
|
||||||
{
|
if (settings.containsKey(setting)) {
|
||||||
if (settings.containsKey(setting))
|
|
||||||
{
|
|
||||||
preferences.putString(setting.c_str(), settings[setting].as<String>());
|
preferences.putString(setting.c_str(), settings[setting].as<String>());
|
||||||
Serial.printf("Setting %s to %s\r\n", setting.c_str(), settings[setting].as<String>());
|
Serial.printf("Setting %s to %s\r\n", setting.c_str(),
|
||||||
|
settings[setting].as<String>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness"};
|
String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness"};
|
||||||
|
|
||||||
for (String setting : uintSettings)
|
for (String setting : uintSettings) {
|
||||||
{
|
if (settings.containsKey(setting)) {
|
||||||
if (settings.containsKey(setting))
|
|
||||||
{
|
|
||||||
preferences.putUInt(setting.c_str(), settings[setting].as<uint>());
|
preferences.putUInt(setting.c_str(), settings[setting].as<uint>());
|
||||||
Serial.printf("Setting %s to %d\r\n", setting.c_str(), settings[setting].as<uint>());
|
Serial.printf("Setting %s to %d\r\n", setting.c_str(),
|
||||||
|
settings[setting].as<uint>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.containsKey("tzOffset")) {
|
||||||
if (settings.containsKey("tzOffset"))
|
|
||||||
{
|
|
||||||
int gmtOffset = settings["tzOffset"].as<int>() * 60;
|
int gmtOffset = settings["tzOffset"].as<int>() * 60;
|
||||||
size_t written = preferences.putInt("gmtOffset", gmtOffset);
|
size_t written = preferences.putInt("gmtOffset", gmtOffset);
|
||||||
Serial.printf("Setting %s to %d (%d minutes, written %d)\r\n", "gmtOffset", gmtOffset, settings["tzOffset"].as<int>(), written);
|
Serial.printf("Setting %s to %d (%d minutes, written %d)\r\n", "gmtOffset",
|
||||||
|
gmtOffset, settings["tzOffset"].as<int>(), written);
|
||||||
}
|
}
|
||||||
|
|
||||||
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd", "mdnsEnabled", "otaEnabled", "stealFocus", "mcapBigChar"};
|
String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd",
|
||||||
|
"mdnsEnabled", "otaEnabled", "stealFocus",
|
||||||
|
"mcapBigChar"};
|
||||||
|
|
||||||
for (String setting : boolSettings)
|
for (String setting : boolSettings) {
|
||||||
{
|
if (settings.containsKey(setting)) {
|
||||||
if (settings.containsKey(setting))
|
|
||||||
{
|
|
||||||
preferences.putBool(setting.c_str(), settings[setting].as<boolean>());
|
preferences.putBool(setting.c_str(), settings[setting].as<boolean>());
|
||||||
Serial.printf("Setting %s to %d\r\n", setting.c_str(), settings[setting].as<boolean>());
|
Serial.printf("Setting %s to %d\r\n", setting.c_str(),
|
||||||
|
settings[setting].as<boolean>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.containsKey("screens"))
|
if (settings.containsKey("screens")) {
|
||||||
{
|
for (JsonVariant screen : settings["screens"].as<JsonArray>()) {
|
||||||
for (JsonVariant screen : settings["screens"].as<JsonArray>())
|
|
||||||
{
|
|
||||||
JsonObject s = screen.as<JsonObject>();
|
JsonObject s = screen.as<JsonObject>();
|
||||||
uint id = s["id"].as<uint>();
|
uint id = s["id"].as<uint>();
|
||||||
String key = "screen[" + String(id) + "]";
|
String key = "screen[" + String(id) + "]";
|
||||||
|
@ -364,11 +347,11 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
if (WiFi.getTxPower() != 80) {
|
if (WiFi.getTxPower() != 80) {
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
} else if (static_cast<int>(wifi_power_t::WIFI_POWER_MINUS_1dBm) <= txPower &&
|
} else if (static_cast<int>(wifi_power_t::WIFI_POWER_MINUS_1dBm) <=
|
||||||
|
txPower &&
|
||||||
txPower <= static_cast<int>(wifi_power_t::WIFI_POWER_19_5dBm)) {
|
txPower <= static_cast<int>(wifi_power_t::WIFI_POWER_19_5dBm)) {
|
||||||
// is valid value
|
// is valid value
|
||||||
|
|
||||||
|
|
||||||
if (WiFi.setTxPower(static_cast<wifi_power_t>(txPower))) {
|
if (WiFi.setTxPower(static_cast<wifi_power_t>(txPower))) {
|
||||||
Serial.printf("Set WiFi Tx power to: %d\n", txPower);
|
Serial.printf("Set WiFi Tx power to: %d\n", txPower);
|
||||||
preferences.putInt("txPower", txPower);
|
preferences.putInt("txPower", txPower);
|
||||||
|
@ -378,14 +361,12 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
if (settingsChanged)
|
if (settingsChanged) {
|
||||||
{
|
|
||||||
queueLedEffect(LED_FLASH_SUCCESS);
|
queueLedEffect(LED_FLASH_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiRestart(AsyncWebServerRequest *request)
|
void onApiRestart(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
|
|
||||||
if (events.count())
|
if (events.count())
|
||||||
|
@ -401,20 +382,22 @@ void onApiRestart(AsyncWebServerRequest *request)
|
||||||
* @Method GET
|
* @Method GET
|
||||||
* @Path("/api/settings")
|
* @Path("/api/settings")
|
||||||
*/
|
*/
|
||||||
void onApiSettingsGet(AsyncWebServerRequest *request)
|
void onApiSettingsGet(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
StaticJsonDocument<1536> root;
|
StaticJsonDocument<1536> root;
|
||||||
root["numScreens"] = NUM_SCREENS;
|
root["numScreens"] = NUM_SCREENS;
|
||||||
root["fgColor"] = getFgColor();
|
root["fgColor"] = getFgColor();
|
||||||
root["bgColor"] = getBgColor();
|
root["bgColor"] = getBgColor();
|
||||||
root["timerSeconds"] = getTimerSeconds();
|
root["timerSeconds"] = getTimerSeconds();
|
||||||
root["timerRunning"] = isTimerActive();
|
root["timerRunning"] = isTimerActive();
|
||||||
root["minSecPriceUpd"] = preferences.getUInt("minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
root["minSecPriceUpd"] = preferences.getUInt(
|
||||||
root["fullRefreshMin"] = preferences.getUInt("fullRefreshMin", DEFAULT_MINUTES_FULL_REFRESH);
|
"minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
||||||
|
root["fullRefreshMin"] =
|
||||||
|
preferences.getUInt("fullRefreshMin", DEFAULT_MINUTES_FULL_REFRESH);
|
||||||
root["wpTimeout"] = preferences.getUInt("wpTimeout", 600);
|
root["wpTimeout"] = preferences.getUInt("wpTimeout", 600);
|
||||||
root["tzOffset"] = preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS) / 60;
|
root["tzOffset"] = preferences.getInt("gmtOffset", TIME_OFFSET_SECONDS) / 60;
|
||||||
root["useBitcoinNode"] = preferences.getBool("useNode", false);
|
root["useBitcoinNode"] = preferences.getBool("useNode", false);
|
||||||
root["mempoolInstance"] = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
root["mempoolInstance"] =
|
||||||
|
preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||||
root["ledTestOnPower"] = preferences.getBool("ledTestOnPower", true);
|
root["ledTestOnPower"] = preferences.getBool("ledTestOnPower", true);
|
||||||
root["ledFlashOnUpd"] = preferences.getBool("ledFlashOnUpd", false);
|
root["ledFlashOnUpd"] = preferences.getBool("ledFlashOnUpd", false);
|
||||||
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
root["ledBrightness"] = preferences.getUInt("ledBrightness", 128);
|
||||||
|
@ -438,8 +421,7 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
std::vector<std::string> screenNameMap = getScreenNameMap();
|
std::vector<std::string> screenNameMap = getScreenNameMap();
|
||||||
|
|
||||||
for (int i = 0; i < screenNameMap.size(); i++)
|
for (int i = 0; i < screenNameMap.size(); i++) {
|
||||||
{
|
|
||||||
JsonObject o = screens.createNestedObject();
|
JsonObject o = screens.createNestedObject();
|
||||||
String key = "screen" + String(i) + "Visible";
|
String key = "screen" + String(i) + "Visible";
|
||||||
o["id"] = i;
|
o["id"] = i;
|
||||||
|
@ -447,17 +429,16 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
o["enabled"] = preferences.getBool(key.c_str(), true);
|
o["enabled"] = preferences.getBool(key.c_str(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
AsyncResponseStream *response =
|
||||||
|
request->beginResponseStream("application/json");
|
||||||
serializeJson(root, *response);
|
serializeJson(root, *response);
|
||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool processEpdColorSettings(AsyncWebServerRequest *request)
|
bool processEpdColorSettings(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
bool settingsChanged = false;
|
bool settingsChanged = false;
|
||||||
if (request->hasParam("fgColor", true))
|
if (request->hasParam("fgColor", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *fgColor = request->getParam("fgColor", true);
|
AsyncWebParameter *fgColor = request->getParam("fgColor", true);
|
||||||
preferences.putUInt("fgColor", strtol(fgColor->value().c_str(), NULL, 16));
|
preferences.putUInt("fgColor", strtol(fgColor->value().c_str(), NULL, 16));
|
||||||
setFgColor(int(strtol(fgColor->value().c_str(), NULL, 16)));
|
setFgColor(int(strtol(fgColor->value().c_str(), NULL, 16)));
|
||||||
|
@ -465,8 +446,7 @@ bool processEpdColorSettings(AsyncWebServerRequest *request)
|
||||||
// Serial.println(fgColor->value().c_str());
|
// Serial.println(fgColor->value().c_str());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
if (request->hasParam("bgColor", true))
|
if (request->hasParam("bgColor", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *bgColor = request->getParam("bgColor", true);
|
AsyncWebParameter *bgColor = request->getParam("bgColor", true);
|
||||||
|
|
||||||
preferences.putUInt("bgColor", strtol(bgColor->value().c_str(), NULL, 16));
|
preferences.putUInt("bgColor", strtol(bgColor->value().c_str(), NULL, 16));
|
||||||
|
@ -479,163 +459,136 @@ bool processEpdColorSettings(AsyncWebServerRequest *request)
|
||||||
return settingsChanged;
|
return settingsChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiSettingsPost(AsyncWebServerRequest *request)
|
void onApiSettingsPost(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
bool settingsChanged = false;
|
bool settingsChanged = false;
|
||||||
|
|
||||||
settingsChanged = processEpdColorSettings(request);
|
settingsChanged = processEpdColorSettings(request);
|
||||||
|
|
||||||
int headers = request->headers();
|
int headers = request->headers();
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < headers; i++)
|
for (i = 0; i < headers; i++) {
|
||||||
{
|
|
||||||
AsyncWebHeader *h = request->getHeader(i);
|
AsyncWebHeader *h = request->getHeader(i);
|
||||||
Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
|
Serial.printf("HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
int params = request->params();
|
int params = request->params();
|
||||||
for (int i = 0; i < params; i++)
|
for (int i = 0; i < params; i++) {
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam(i);
|
AsyncWebParameter *p = request->getParam(i);
|
||||||
if (p->isFile())
|
if (p->isFile()) { // p->isPost() is also true
|
||||||
{ // p->isPost() is also true
|
Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(),
|
||||||
Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
|
p->value().c_str(), p->size());
|
||||||
}
|
} else if (p->isPost()) {
|
||||||
else if (p->isPost())
|
|
||||||
{
|
|
||||||
Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("fetchEurPrice", true))
|
if (request->hasParam("fetchEurPrice", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *fetchEurPrice = request->getParam("fetchEurPrice", true);
|
AsyncWebParameter *fetchEurPrice = request->getParam("fetchEurPrice", true);
|
||||||
|
|
||||||
preferences.putBool("fetchEurPrice", fetchEurPrice->value().toInt());
|
preferences.putBool("fetchEurPrice", fetchEurPrice->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("fetchEurPrice", 0);
|
preferences.putBool("fetchEurPrice", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("ledTestOnPower", true))
|
if (request->hasParam("ledTestOnPower", true)) {
|
||||||
{
|
AsyncWebParameter *ledTestOnPower =
|
||||||
AsyncWebParameter *ledTestOnPower = request->getParam("ledTestOnPower", true);
|
request->getParam("ledTestOnPower", true);
|
||||||
|
|
||||||
preferences.putBool("ledTestOnPower", ledTestOnPower->value().toInt());
|
preferences.putBool("ledTestOnPower", ledTestOnPower->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("ledTestOnPower", 0);
|
preferences.putBool("ledTestOnPower", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("ledFlashOnUpd", true))
|
if (request->hasParam("ledFlashOnUpd", true)) {
|
||||||
{
|
AsyncWebParameter *ledFlashOnUpdate =
|
||||||
AsyncWebParameter *ledFlashOnUpdate = request->getParam("ledFlashOnUpd", true);
|
request->getParam("ledFlashOnUpd", true);
|
||||||
|
|
||||||
preferences.putBool("ledFlashOnUpd", ledFlashOnUpdate->value().toInt());
|
preferences.putBool("ledFlashOnUpd", ledFlashOnUpdate->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("ledFlashOnUpd", 0);
|
preferences.putBool("ledFlashOnUpd", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("mdnsEnabled", true))
|
if (request->hasParam("mdnsEnabled", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *mdnsEnabled = request->getParam("mdnsEnabled", true);
|
AsyncWebParameter *mdnsEnabled = request->getParam("mdnsEnabled", true);
|
||||||
|
|
||||||
preferences.putBool("mdnsEnabled", mdnsEnabled->value().toInt());
|
preferences.putBool("mdnsEnabled", mdnsEnabled->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("mdnsEnabled", 0);
|
preferences.putBool("mdnsEnabled", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("otaEnabled", true))
|
if (request->hasParam("otaEnabled", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *otaEnabled = request->getParam("otaEnabled", true);
|
AsyncWebParameter *otaEnabled = request->getParam("otaEnabled", true);
|
||||||
|
|
||||||
preferences.putBool("otaEnabled", otaEnabled->value().toInt());
|
preferences.putBool("otaEnabled", otaEnabled->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("otaEnabled", 0);
|
preferences.putBool("otaEnabled", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("stealFocusOnBlock", true))
|
if (request->hasParam("stealFocusOnBlock", true)) {
|
||||||
{
|
AsyncWebParameter *stealFocusOnBlock =
|
||||||
AsyncWebParameter *stealFocusOnBlock = request->getParam("stealFocusOnBlock", true);
|
request->getParam("stealFocusOnBlock", true);
|
||||||
|
|
||||||
preferences.putBool("stealFocus", stealFocusOnBlock->value().toInt());
|
preferences.putBool("stealFocus", stealFocusOnBlock->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("stealFocus", 0);
|
preferences.putBool("stealFocus", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("mcapBigChar", true))
|
if (request->hasParam("mcapBigChar", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *mcapBigChar = request->getParam("mcapBigChar", true);
|
AsyncWebParameter *mcapBigChar = request->getParam("mcapBigChar", true);
|
||||||
|
|
||||||
preferences.putBool("mcapBigChar", mcapBigChar->value().toInt());
|
preferences.putBool("mcapBigChar", mcapBigChar->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
preferences.putBool("mcapBigChar", 0);
|
preferences.putBool("mcapBigChar", 0);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("mempoolInstance", true))
|
if (request->hasParam("mempoolInstance", true)) {
|
||||||
{
|
AsyncWebParameter *mempoolInstance =
|
||||||
AsyncWebParameter *mempoolInstance = request->getParam("mempoolInstance", true);
|
request->getParam("mempoolInstance", true);
|
||||||
|
|
||||||
preferences.putString("mempoolInstance", mempoolInstance->value().c_str());
|
preferences.putString("mempoolInstance", mempoolInstance->value().c_str());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("hostnamePrefix", true))
|
if (request->hasParam("hostnamePrefix", true)) {
|
||||||
{
|
AsyncWebParameter *hostnamePrefix =
|
||||||
AsyncWebParameter *hostnamePrefix = request->getParam("hostnamePrefix", true);
|
request->getParam("hostnamePrefix", true);
|
||||||
|
|
||||||
preferences.putString("hostnamePrefix", hostnamePrefix->value().c_str());
|
preferences.putString("hostnamePrefix", hostnamePrefix->value().c_str());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("ledBrightness", true))
|
if (request->hasParam("ledBrightness", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *ledBrightness = request->getParam("ledBrightness", true);
|
AsyncWebParameter *ledBrightness = request->getParam("ledBrightness", true);
|
||||||
|
|
||||||
preferences.putUInt("ledBrightness", ledBrightness->value().toInt());
|
preferences.putUInt("ledBrightness", ledBrightness->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("fullRefreshMin", true))
|
if (request->hasParam("fullRefreshMin", true)) {
|
||||||
{
|
AsyncWebParameter *fullRefreshMin =
|
||||||
AsyncWebParameter *fullRefreshMin = request->getParam("fullRefreshMin", true);
|
request->getParam("fullRefreshMin", true);
|
||||||
|
|
||||||
preferences.putUInt("fullRefreshMin", fullRefreshMin->value().toInt());
|
preferences.putUInt("fullRefreshMin", fullRefreshMin->value().toInt());
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("wpTimeout", true))
|
if (request->hasParam("wpTimeout", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *wpTimeout = request->getParam("wpTimeout", true);
|
AsyncWebParameter *wpTimeout = request->getParam("wpTimeout", true);
|
||||||
|
|
||||||
preferences.putUInt("wpTimeout", wpTimeout->value().toInt());
|
preferences.putUInt("wpTimeout", wpTimeout->value().toInt());
|
||||||
|
@ -644,20 +597,17 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
std::vector<std::string> screenNameMap = getScreenNameMap();
|
std::vector<std::string> screenNameMap = getScreenNameMap();
|
||||||
|
|
||||||
if (request->hasParam("screens"))
|
if (request->hasParam("screens")) {
|
||||||
{
|
|
||||||
AsyncWebParameter *screenParam = request->getParam("screens", true);
|
AsyncWebParameter *screenParam = request->getParam("screens", true);
|
||||||
|
|
||||||
Serial.printf(screenParam->value().c_str());
|
Serial.printf(screenParam->value().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < screenNameMap.size(); i++)
|
for (int i = 0; i < screenNameMap.size(); i++) {
|
||||||
{
|
|
||||||
String key = "screen[" + String(i) + "]";
|
String key = "screen[" + String(i) + "]";
|
||||||
String prefKey = "screen" + String(i) + "Visible";
|
String prefKey = "screen" + String(i) + "Visible";
|
||||||
bool visible = false;
|
bool visible = false;
|
||||||
if (request->hasParam(key, true))
|
if (request->hasParam(key, true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *screenParam = request->getParam(key, true);
|
AsyncWebParameter *screenParam = request->getParam(key, true);
|
||||||
visible = screenParam->value().toInt();
|
visible = screenParam->value().toInt();
|
||||||
}
|
}
|
||||||
|
@ -665,24 +615,21 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
preferences.putBool(prefKey.c_str(), visible);
|
preferences.putBool(prefKey.c_str(), visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("tzOffset", true))
|
if (request->hasParam("tzOffset", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam("tzOffset", true);
|
AsyncWebParameter *p = request->getParam("tzOffset", true);
|
||||||
int tzOffsetSeconds = p->value().toInt() * 60;
|
int tzOffsetSeconds = p->value().toInt() * 60;
|
||||||
preferences.putInt("gmtOffset", tzOffsetSeconds);
|
preferences.putInt("gmtOffset", tzOffsetSeconds);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("minSecPriceUpd", true))
|
if (request->hasParam("minSecPriceUpd", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam("minSecPriceUpd", true);
|
AsyncWebParameter *p = request->getParam("minSecPriceUpd", true);
|
||||||
int minSecPriceUpd = p->value().toInt();
|
int minSecPriceUpd = p->value().toInt();
|
||||||
preferences.putUInt("minSecPriceUpd", minSecPriceUpd);
|
preferences.putUInt("minSecPriceUpd", minSecPriceUpd);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->hasParam("timePerScreen", true))
|
if (request->hasParam("timePerScreen", true)) {
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam("timePerScreen", true);
|
AsyncWebParameter *p = request->getParam("timePerScreen", true);
|
||||||
uint timerSeconds = p->value().toInt() * 60;
|
uint timerSeconds = p->value().toInt() * 60;
|
||||||
preferences.putUInt("timerSeconds", timerSeconds);
|
preferences.putUInt("timerSeconds", timerSeconds);
|
||||||
|
@ -690,15 +637,14 @@ void onApiSettingsPost(AsyncWebServerRequest *request)
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
if (settingsChanged)
|
if (settingsChanged) {
|
||||||
{
|
|
||||||
queueLedEffect(LED_FLASH_SUCCESS);
|
queueLedEffect(LED_FLASH_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiSystemStatus(AsyncWebServerRequest *request)
|
void onApiSystemStatus(AsyncWebServerRequest *request) {
|
||||||
{
|
AsyncResponseStream *response =
|
||||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
request->beginResponseStream("application/json");
|
||||||
|
|
||||||
StaticJsonDocument<128> root;
|
StaticJsonDocument<128> root;
|
||||||
|
|
||||||
|
@ -717,16 +663,17 @@ void onApiSystemStatus(AsyncWebServerRequest *request)
|
||||||
#define STRINGIFY(x) #x
|
#define STRINGIFY(x) #x
|
||||||
#define ENUM_TO_STRING(x) STRINGIFY(x)
|
#define ENUM_TO_STRING(x) STRINGIFY(x)
|
||||||
|
|
||||||
|
void onApiSetWifiTxPower(AsyncWebServerRequest *request) {
|
||||||
void onApiSetWifiTxPower(AsyncWebServerRequest *request)
|
|
||||||
{
|
|
||||||
if (request->hasParam("txPower")) {
|
if (request->hasParam("txPower")) {
|
||||||
AsyncWebParameter *txPowerParam = request->getParam("txPower");
|
AsyncWebParameter *txPowerParam = request->getParam("txPower");
|
||||||
int txPower = txPowerParam->value().toInt();
|
int txPower = txPowerParam->value().toInt();
|
||||||
if (static_cast<int>(wifi_power_t::WIFI_POWER_MINUS_1dBm) <= txPower &&
|
if (static_cast<int>(wifi_power_t::WIFI_POWER_MINUS_1dBm) <= txPower &&
|
||||||
txPower <= static_cast<int>(wifi_power_t::WIFI_POWER_19_5dBm)) {
|
txPower <= static_cast<int>(wifi_power_t::WIFI_POWER_19_5dBm)) {
|
||||||
// is valid value
|
// is valid value
|
||||||
String txPowerName = std::to_string(static_cast<std::underlying_type_t<wifi_power_t>>(txPower)).c_str();
|
String txPowerName =
|
||||||
|
std::to_string(
|
||||||
|
static_cast<std::underlying_type_t<wifi_power_t>>(txPower))
|
||||||
|
.c_str();
|
||||||
|
|
||||||
Serial.printf("Set WiFi Tx power to: %s\n", txPowerName);
|
Serial.printf("Set WiFi Tx power to: %s\n", txPowerName);
|
||||||
|
|
||||||
|
@ -741,36 +688,30 @@ void onApiSetWifiTxPower(AsyncWebServerRequest *request)
|
||||||
return request->send(400);
|
return request->send(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onApiLightsStatus(AsyncWebServerRequest *request) {
|
||||||
void onApiLightsStatus(AsyncWebServerRequest *request)
|
AsyncResponseStream *response =
|
||||||
{
|
request->beginResponseStream("application/json");
|
||||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
|
||||||
|
|
||||||
serializeJson(getLedStatusObject()["data"], *response);
|
serializeJson(getLedStatusObject()["data"], *response);
|
||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiLightsOff(AsyncWebServerRequest *request)
|
void onApiLightsOff(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
setLights(0, 0, 0);
|
setLights(0, 0, 0);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiLightsSetColor(AsyncWebServerRequest *request)
|
void onApiLightsSetColor(AsyncWebServerRequest *request) {
|
||||||
{
|
if (request->hasParam("c")) {
|
||||||
if (request->hasParam("c"))
|
AsyncResponseStream *response =
|
||||||
{
|
request->beginResponseStream("application/json");
|
||||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
|
||||||
|
|
||||||
String rgbColor = request->getParam("c")->value();
|
String rgbColor = request->getParam("c")->value();
|
||||||
|
|
||||||
if (rgbColor.compareTo("off") == 0)
|
if (rgbColor.compareTo("off") == 0) {
|
||||||
{
|
|
||||||
setLights(0, 0, 0);
|
setLights(0, 0, 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uint r, g, b;
|
uint r, g, b;
|
||||||
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||||
setLights(r, g, b);
|
setLights(r, g, b);
|
||||||
|
@ -779,7 +720,6 @@ void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||||
StaticJsonDocument<48> doc;
|
StaticJsonDocument<48> doc;
|
||||||
doc["result"] = rgbColor;
|
doc["result"] = rgbColor;
|
||||||
|
|
||||||
|
|
||||||
serializeJson(getLedStatusObject()["data"], *response);
|
serializeJson(getLedStatusObject()["data"], *response);
|
||||||
|
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
@ -788,48 +728,39 @@ void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
|
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json) {
|
||||||
{
|
|
||||||
JsonArray lights = json.as<JsonArray>();
|
JsonArray lights = json.as<JsonArray>();
|
||||||
|
|
||||||
if (lights.size() != pixels.numPixels())
|
if (lights.size() != pixels.numPixels()) {
|
||||||
{
|
|
||||||
Serial.printf("Invalid values for LED set %d\n", lights.size());
|
Serial.printf("Invalid values for LED set %d\n", lights.size());
|
||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i = 0; i < pixels.numPixels(); i++)
|
for (uint i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
|
||||||
unsigned int red, green, blue;
|
unsigned int red, green, blue;
|
||||||
|
|
||||||
if (lights[i].containsKey("red") && lights[i].containsKey("green") && lights[i].containsKey("blue"))
|
if (lights[i].containsKey("red") && lights[i].containsKey("green") &&
|
||||||
{
|
lights[i].containsKey("blue")) {
|
||||||
|
|
||||||
red = lights[i]["red"].as<uint>();
|
red = lights[i]["red"].as<uint>();
|
||||||
green = lights[i]["green"].as<uint>();
|
green = lights[i]["green"].as<uint>();
|
||||||
blue = lights[i]["blue"].as<uint>();
|
blue = lights[i]["blue"].as<uint>();
|
||||||
}
|
} else if (lights[i].containsKey("hex")) {
|
||||||
else if (lights[i].containsKey("hex"))
|
if (!sscanf(lights[i]["hex"].as<String>().c_str(), "#%02X%02X%02X", &red,
|
||||||
{
|
&green, &blue) == 3) {
|
||||||
if (!sscanf(lights[i]["hex"].as<String>().c_str(), "#%02X%02X%02X", &red, &green, &blue) == 3)
|
|
||||||
{
|
|
||||||
Serial.printf("Invalid hex for LED %d\n", i);
|
Serial.printf("Invalid hex for LED %d\n", i);
|
||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Serial.printf("No valid color for LED %d\n", i);
|
Serial.printf("No valid color for LED %d\n", i);
|
||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels.setPixelColor((pixels.numPixels() - i - 1), pixels.Color(
|
pixels.setPixelColor((pixels.numPixels() - i - 1),
|
||||||
red,
|
pixels.Color(red, green, blue));
|
||||||
green,
|
|
||||||
blue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels.show();
|
pixels.show();
|
||||||
|
@ -838,10 +769,11 @@ void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onIndex(AsyncWebServerRequest *request) { request->send(LittleFS, "/index.html", String(), false); }
|
void onIndex(AsyncWebServerRequest *request) {
|
||||||
|
request->send(LittleFS, "/index.html", String(), false);
|
||||||
|
}
|
||||||
|
|
||||||
void onNotFound(AsyncWebServerRequest *request)
|
void onNotFound(AsyncWebServerRequest *request) {
|
||||||
{
|
|
||||||
// Serial.printf("NotFound, URL[%s]\n", request->url());
|
// Serial.printf("NotFound, URL[%s]\n", request->url());
|
||||||
|
|
||||||
// Serial.printf("NotFound, METHOD[%s]\n", request->methodToString());
|
// Serial.printf("NotFound, METHOD[%s]\n", request->methodToString());
|
||||||
|
@ -851,7 +783,8 @@ void onNotFound(AsyncWebServerRequest *request)
|
||||||
// for (i = 0; i < headers; i++)
|
// for (i = 0; i < headers; i++)
|
||||||
// {
|
// {
|
||||||
// AsyncWebHeader *h = request->getHeader(i);
|
// AsyncWebHeader *h = request->getHeader(i);
|
||||||
// Serial.printf("NotFound HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
|
// Serial.printf("NotFound HEADER[%s]: %s\n", h->name().c_str(),
|
||||||
|
// h->value().c_str());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// int params = request->params();
|
// int params = request->params();
|
||||||
|
@ -860,37 +793,36 @@ void onNotFound(AsyncWebServerRequest *request)
|
||||||
// AsyncWebParameter *p = request->getParam(i);
|
// AsyncWebParameter *p = request->getParam(i);
|
||||||
// if (p->isFile())
|
// if (p->isFile())
|
||||||
// { // p->isPost() is also true
|
// { // p->isPost() is also true
|
||||||
// Serial.printf("NotFound FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
|
// Serial.printf("NotFound FILE[%s]: %s, size: %u\n",
|
||||||
|
// p->name().c_str(), p->value().c_str(), p->size());
|
||||||
// }
|
// }
|
||||||
// else if (p->isPost())
|
// else if (p->isPost())
|
||||||
// {
|
// {
|
||||||
// Serial.printf("NotFound POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
// Serial.printf("NotFound POST[%s]: %s\n", p->name().c_str(),
|
||||||
|
// p->value().c_str());
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
// Serial.printf("NotFound GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
|
// Serial.printf("NotFound GET[%s]: %s\n", p->name().c_str(),
|
||||||
|
// p->value().c_str());
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Access-Control-Request-Method == POST might be better
|
// Access-Control-Request-Method == POST might be better
|
||||||
|
|
||||||
if (request->method() == HTTP_OPTIONS || request->hasHeader("Sec-Fetch-Mode"))
|
if (request->method() == HTTP_OPTIONS ||
|
||||||
{
|
request->hasHeader("Sec-Fetch-Mode")) {
|
||||||
// Serial.printf("NotFound, Return[%d]\n", 200);
|
// Serial.printf("NotFound, Return[%d]\n", 200);
|
||||||
|
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Serial.printf("NotFound, Return[%d]\n", 404);
|
// Serial.printf("NotFound, Return[%d]\n", 404);
|
||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void eventSourceTask(void *pvParameters)
|
void eventSourceTask(void *pvParameters) {
|
||||||
{
|
for (;;) {
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
eventSourceUpdate();
|
eventSourceUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "WebServer.h"
|
#include "WebServer.h"
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
@ -7,10 +8,19 @@
|
||||||
#include "AsyncJson.h"
|
#include "AsyncJson.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
// #include "AsyncJson.h"
|
||||||
|
// #include "ESPAsyncWebServer.h"
|
||||||
|
// #include "WebServer.h"
|
||||||
|
// #include <ArduinoJson.h>
|
||||||
|
// #include <ESPmDNS.h>
|
||||||
|
// #include <LittleFS.h>
|
||||||
|
// #include <iostream>
|
||||||
|
|
||||||
#include "lib/block_notify.hpp"
|
#include "lib/block_notify.hpp"
|
||||||
|
#include "lib/led_handler.hpp"
|
||||||
#include "lib/price_notify.hpp"
|
#include "lib/price_notify.hpp"
|
||||||
#include "lib/screen_handler.hpp"
|
#include "lib/screen_handler.hpp"
|
||||||
#include "lib/led_handler.hpp"
|
|
||||||
|
|
||||||
#include "webserver/OneParamRewrite.hpp"
|
#include "webserver/OneParamRewrite.hpp"
|
||||||
|
|
||||||
|
@ -40,7 +50,6 @@ void onApiLightsOff(AsyncWebServerRequest *request);
|
||||||
void onApiLightsSetColor(AsyncWebServerRequest *request);
|
void onApiLightsSetColor(AsyncWebServerRequest *request);
|
||||||
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json);
|
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json);
|
||||||
|
|
||||||
|
|
||||||
void onApiRestart(AsyncWebServerRequest *request);
|
void onApiRestart(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
void onIndex(AsyncWebServerRequest *request);
|
void onIndex(AsyncWebServerRequest *request);
|
||||||
|
|
|
@ -1,43 +1,31 @@
|
||||||
#include "OneParamRewrite.hpp"
|
#include "OneParamRewrite.hpp"
|
||||||
|
|
||||||
OneParamRewrite::OneParamRewrite(const char *from, const char *to)
|
OneParamRewrite::OneParamRewrite(const char *from, const char *to)
|
||||||
: AsyncWebRewrite(from, to)
|
: AsyncWebRewrite(from, to) {
|
||||||
{
|
|
||||||
|
|
||||||
_paramIndex = _from.indexOf('{');
|
_paramIndex = _from.indexOf('{');
|
||||||
|
|
||||||
if (_paramIndex >= 0 && _from.endsWith("}"))
|
if (_paramIndex >= 0 && _from.endsWith("}")) {
|
||||||
{
|
|
||||||
_urlPrefix = _from.substring(0, _paramIndex);
|
_urlPrefix = _from.substring(0, _paramIndex);
|
||||||
int index = _params.indexOf('{');
|
int index = _params.indexOf('{');
|
||||||
if (index >= 0)
|
if (index >= 0) {
|
||||||
{
|
|
||||||
_params = _params.substring(0, index);
|
_params = _params.substring(0, index);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
_urlPrefix = _from;
|
_urlPrefix = _from;
|
||||||
}
|
}
|
||||||
_paramsBackup = _params;
|
_paramsBackup = _params;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneParamRewrite::match(AsyncWebServerRequest *request)
|
bool OneParamRewrite::match(AsyncWebServerRequest *request) {
|
||||||
{
|
if (request->url().startsWith(_urlPrefix)) {
|
||||||
if (request->url().startsWith(_urlPrefix))
|
if (_paramIndex >= 0) {
|
||||||
{
|
|
||||||
if (_paramIndex >= 0)
|
|
||||||
{
|
|
||||||
_params = _paramsBackup + request->url().substring(_paramIndex);
|
_params = _paramsBackup + request->url().substring(_paramIndex);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
_params = _paramsBackup;
|
_params = _paramsBackup;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
class OneParamRewrite : public AsyncWebRewrite
|
class OneParamRewrite : public AsyncWebRewrite {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
String _urlPrefix;
|
String _urlPrefix;
|
||||||
int _paramIndex;
|
int _paramIndex;
|
||||||
|
|
24
src/main.cpp
24
src/main.cpp
|
@ -1,23 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Djuri Baars
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <WiFiManager.h>
|
#include <WiFiManager.h>
|
||||||
#define WEBSERVER_H
|
#define WEBSERVER_H
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
#include "lib/config.hpp"
|
#include "lib/config.hpp"
|
||||||
|
|
||||||
//char ptrTaskList[400];
|
|
||||||
|
|
||||||
uint wifiLostConnection;
|
uint wifiLostConnection;
|
||||||
|
|
||||||
extern "C" void app_main()
|
extern "C" void app_main() {
|
||||||
{
|
|
||||||
initArduino();
|
initArduino();
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
while (true)
|
while (true) {
|
||||||
{
|
|
||||||
// vTaskList(ptrTaskList);
|
// vTaskList(ptrTaskList);
|
||||||
// Serial.println(F("**********************************"));
|
// Serial.println(F("**********************************"));
|
||||||
// Serial.println(F("Task State Prio Stack Num"));
|
// Serial.println(F("Task State Prio Stack Num"));
|
||||||
|
|
Loading…
Reference in a new issue