Working with QR code config, very memory consuming

This commit is contained in:
Djuri 2023-11-10 13:02:05 +01:00
parent 8bad5ebafa
commit f611d2f5f8
13 changed files with 1659 additions and 70 deletions

View file

@ -1,7 +1,5 @@
#include "config.hpp"
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
Preferences preferences;
@ -14,6 +12,8 @@ void setup()
setupHardware();
if (mcp.digitalRead(3) == LOW)
{
preferences.putBool("wifiConfigured", false);
WiFi.eraseAP();
blinkDelay(100, 3);
}
@ -29,43 +29,90 @@ void setup()
setupTasks();
setupTimers();
setupWebsocketClients();
xTaskCreate(setupWebsocketClients, "setupWebsocketClients", 4096, NULL, tskIDLE_PRIORITY, NULL);
setupButtonTask();
}
void tryImprovSetup()
{
// if (mcp.digitalRead(3) == LOW)
// {
// WiFi.persistent(false);
// blinkDelay(100, 3);
// }
// else
if (!preferences.getBool("wifiConfigured", false))
{
WiFi.begin();
}
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
uint8_t x_buffer[16];
uint8_t x_position = 0;
uint8_t x_buffer[16];
uint8_t x_position = 0;
while (WiFi.status() != WL_CONNECTED)
{
if (Serial.available() > 0)
// Hold second button to start QR code wifi config
if (!mcp.digitalRead(2) == LOW)
{
uint8_t b = Serial.read();
WiFiManager wm;
if (parse_improv_serial_byte(x_position, b, x_buffer, onImprovCommandCallback, onImprovErrorCallback))
byte mac[6];
WiFi.macAddress(mac);
String softAP_SSID = String("BTClock" + String(mac[5], 16) + String(mac[1], 16));
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);
wm.setConfigPortalTimeout(preferences.getUInt("wpTimeout", 600));
wm.setWiFiAutoReconnect(true);
wm.setAPCallback([&](WiFiManager *wifiManager)
{
Serial.printf("Entered config mode:ip=%s, ssid='%s', pass='%s'\n",
WiFi.softAPIP().toString().c_str(),
wifiManager->getConfigPortalSSID().c_str(),
softAP_password.c_str());
// vTaskDelay(pdMS_TO_TICKS(1000));
delay(1000);
const String qrText = "qrWIFI:S:" + wifiManager->getConfigPortalSSID() + ";T:WPA;P:" + softAP_password.c_str() + ";;";
const String explainText = "*SSID: *\r\n" + wifiManager->getConfigPortalSSID() + "\r\n\r\n*Password:*\r\n" + softAP_password;
std::array<String, NUM_SCREENS> epdContent = {"Welcome!", "", "To setup\r\nscan QR or\r\nconnect\r\nmanually", "", explainText, "", qrText};
setEpdContent(epdContent);
});
wm.setSaveConfigCallback([]() {
preferences.putBool("wifiConfigured", true);
});
bool ac = wm.autoConnect(softAP_SSID.c_str(), softAP_password.c_str());
wm.server->stop();
}
else
{
while (WiFi.status() != WL_CONNECTED)
{
x_buffer[x_position++] = b;
}
else
{
x_position = 0;
if (Serial.available() > 0)
{
uint8_t b = Serial.read();
if (parse_improv_serial_byte(x_position, b, x_buffer, onImprovCommandCallback, onImprovErrorCallback))
{
x_buffer[x_position++] = b;
}
else
{
x_position = 0;
}
}
esp_task_wdt_reset();
}
}
esp_task_wdt_reset();
}
else
{
WiFi.begin();
while (WiFi.status() != WL_CONNECTED)
{
vTaskDelay(pdMS_TO_TICKS(400));
}
}
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
}
void setupTime()
@ -90,17 +137,19 @@ void setupPreferences()
setFgColor(preferences.getUInt("fgColor", DEFAULT_FG_COLOR));
setBgColor(preferences.getUInt("bgColor", DEFAULT_BG_COLOR));
screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
screenNameMap[SCREEN_BLOCK_HEIGHT] = "Block Height";
screenNameMap[SCREEN_MSCW_TIME] = "Sats per dollar";
screenNameMap[SCREEN_BTC_TICKER] = "Ticker";
screenNameMap[SCREEN_TIME] = "Time";
screenNameMap[SCREEN_BTC_TICKER] = "Ticker";
screenNameMap[SCREEN_TIME] = "Time";
screenNameMap[SCREEN_HALVING_COUNTDOWN] = "Halving countdown";
}
void setupWebsocketClients()
void setupWebsocketClients(void *pvParameters)
{
setupBlockNotify();
setupPriceNotify();
vTaskDelete(NULL);
}
void setupTimers()
@ -112,22 +161,27 @@ void setupTimers()
void finishSetup()
{
if (preferences.getBool("ledStatus", false)) {
if (preferences.getBool("ledStatus", false))
{
setLights(preferences.getUInt("ledColor", 0xFFCC00));
} else {
}
else
{
clearLeds();
}
}
std::vector<std::string> getScreenNameMap() {
std::vector<std::string> getScreenNameMap()
{
return screenNameMap;
}
void setupHardware()
{
setupLeds();
WiFi.setHostname(getMyHostname().c_str());;
WiFi.setHostname(getMyHostname().c_str());
;
if (psramInit())
{
Serial.println(F("PSRAM is correctly initialized"));
@ -200,10 +254,9 @@ bool improv_connectWifi(std::string ssid, std::string password)
return true;
}
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(1, pixels.Color(255, 0, 0));
// pixels.setPixelColor(2, pixels.Color(255, 0, 0));
@ -254,14 +307,18 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
}
improv_set_state(improv::STATE_PROVISIONING);
queueLedEffect(LED_EFFECT_WIFI_CONNECTING);
if (improv_connectWifi(cmd.ssid, cmd.password))
{
blinkDelay(100, 3);
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
// std::array<String, NUM_SCREENS> epdContent = {"S", "U", "C", "C", "E", "S", "S"};
// setEpdContent(epdContent);
preferences.putBool("wifiConfigured", true);
improv_set_state(improv::STATE_PROVISIONED);
std::vector<uint8_t> data = improv::build_rpc_response(improv::WIFI_SETTINGS, getLocalUrl(), false);
improv_send_response(data);
@ -269,6 +326,8 @@ bool onImprovCommandCallback(improv::ImprovCommand cmd)
}
else
{
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
improv_set_state(improv::STATE_STOPPED);
improv_set_error(improv::Error::ERROR_UNABLE_TO_CONNECT);
}

View file

@ -1,15 +1,14 @@
#pragma once;
#include <WiFiManager.h>
#include "base64.h"
#include <WiFiClientSecure.h>
#include <Preferences.h>
#include <Adafruit_MCP23X17.h>
#include "shared.hpp"
#include <esp_system.h>
#include <esp_netif.h>
#include <esp_sntp.h>
#include "epd.hpp"
#include "improv.hpp"
#include "hal/wdt_hal.h"
#include "esp_task_wdt.h"
#include <map>
@ -21,6 +20,7 @@
#include "lib/button_handler.hpp"
#include "lib/led_handler.hpp"
#define NTP_SERVER "pool.ntp.org"
#define DEFAULT_MEMPOOL_INSTANCE "mempool.space"
#define TIME_OFFSET_SECONDS 3600
@ -39,7 +39,7 @@
void setup();
void setupTime();
void setupPreferences();
void setupWebsocketClients();
void setupWebsocketClients(void *pvParameters);
void setupHardware();
void tryImprovSetup();
void setupTimers();

View file

@ -63,6 +63,8 @@ int bgColor = GxEPD_BLACK;
#define FONT_SMALL Antonio_SemiBold20pt7b
#define FONT_BIG Antonio_SemiBold90pt7b
uint8_t qrcode[800];
void setupDisplays()
{
for (uint i = 0; i < NUM_SCREENS; i++)
@ -78,7 +80,7 @@ void setupDisplays()
int *taskParam = new int;
*taskParam = i;
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 4096, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 10000, taskParam, tskIDLE_PRIORITY, &tasks[i]); // create task
}
xTaskCreate(taskEpd, "epd_task", 2048, NULL, tskIDLE_PRIORITY, &epdTaskHandle);
@ -92,10 +94,10 @@ void setupDisplays()
"K"};
setEpdContent(epdContent);
// for (uint i = 0; i < NUM_SCREENS; i++)
// {
// xTaskNotifyGive(tasks[i]);
// }
for (uint i = 0; i < NUM_SCREENS; i++)
{
xTaskNotifyGive(tasks[i]);
}
}
void taskEpd(void *pvParameters)
@ -186,6 +188,14 @@ extern "C" void updateDisplay(void *pvParameters) noexcept
splitText(epdIndex, top, bottom, updatePartial);
#endif
}
else if (epdContent[epdIndex].startsWith(F("qr")))
{
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
}
else if (epdContent[epdIndex].length() > 5)
{
renderText(epdIndex, epdContent[epdIndex], updatePartial);
}
else
{
@ -223,7 +233,7 @@ void updateDisplayAlt(int epdIndex)
{
}
void splitText(const uint dispNum, String top, String bottom, bool partial)
void splitText(const uint dispNum, const String &top, const String &bottom, bool partial)
{
displays[dispNum].setRotation(2);
displays[dispNum].setFont(&FONT_SMALL);
@ -384,3 +394,63 @@ std::array<String, NUM_SCREENS> getCurrentEpdContent()
// }
return currentEpdContent;
}
void renderText(const uint dispNum, const String &text, bool partial)
{
displays[dispNum].setRotation(2);
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
displays[dispNum].fillScreen(GxEPD_WHITE);
displays[dispNum].setTextColor(GxEPD_BLACK);
displays[dispNum].setCursor(0, 50);
// displays[dispNum].setFont(&FreeSans9pt7b);
// std::regex pattern("/\*(.*)\*/");
std::stringstream ss;
ss.str(text.c_str());
std::string line;
while (std::getline(ss, line, '\n'))
{
if (line.rfind("*", 0) == 0)
{
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
displays[dispNum].setFont(&FreeSansBold9pt7b);
displays[dispNum].println(line.c_str());
}
else
{
displays[dispNum].setFont(&FreeSans9pt7b);
displays[dispNum].println(line.c_str());
}
}
displays[dispNum].display(partial);
}
void renderQr(const uint dispNum, const String &text, bool partial)
{
uint8_t tempBuffer[800];
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
const int size = qrcodegen_getSize(qrcode);
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
const int paddingY = floor(float(displays[dispNum].height() - (size * 4)) / 2);
displays[dispNum].setRotation(2);
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
displays[dispNum].fillScreen(GxEPD_WHITE);
const int border = 0;
for (int y = -border; y < size * 4 + border; y++)
{
for (int x = -border; x < size * 4 + border; x++)
{
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
}
}
displays[dispNum].display(partial);
}

View file

@ -6,11 +6,16 @@
#include "shared.hpp"
#include "config.hpp"
#include "fonts/fonts.hpp"
#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include <regex>
#include "qrcodegen.h"
void setupDisplays();
void taskEpd(void *pvParameters);
void splitText(const uint dispNum, String top, String bottom, bool partial);
void splitText(const uint dispNum, const String& top, const String& bottom, bool partial);
void splitTextPaged(const uint dispNum, String top, String bottom, bool partial);
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
@ -24,5 +29,8 @@ int getFgColor();
void setBgColor(int color);
void setFgColor(int color);
void renderText(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);
std::array<String, NUM_SCREENS> getCurrentEpdContent();

View file

@ -23,17 +23,40 @@ void ledTask(void *parameter)
switch (ledTaskParams)
{
case LED_EFFECT_WIFI_CONNECT_ERROR:
case LED_FLASH_ERROR:
blinkDelayColor(250, 3, 255, 0, 0);
break;
case LED_EFFECT_WIFI_CONNECT_SUCCESS:
case LED_FLASH_SUCCESS:
blinkDelayColor(250, 3, 0, 255, 0);
blinkDelayColor(150, 3, 0, 255, 0);
break;
case LED_FLASH_UPDATE:
break;
case LED_FLASH_BLOCK_NOTIFY:
blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0), pixels.Color(8, 2, 0));
break;
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), pixels.Color(156, 225, 240));
break;
case LED_EFFECT_WIFI_CONNECTING:
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
{
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
{
if (j == i)
{
pixels.setPixelColor(i, pixels.Color(16, 197, 236));
}
else
{
pixels.setPixelColor(j, pixels.Color(0, 0, 0));
}
}
pixels.show();
vTaskDelay(pdMS_TO_TICKS(100));
}
break;
case LED_EFFECT_PAUSE_TIMER:
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
{
@ -59,7 +82,7 @@ void ledTask(void *parameter)
break;
case LED_EFFECT_START_TIMER:
pixels.clear();
pixels.setPixelColor((NEOPIXEL_COUNT-1), pixels.Color(255, 0, 0));
pixels.setPixelColor((NEOPIXEL_COUNT - 1), pixels.Color(255, 0, 0));
pixels.show();
delay(900);
@ -101,18 +124,25 @@ void ledTask(void *parameter)
void setupLeds()
{
pixels.begin();
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
pixels.setPixelColor(2, pixels.Color(0, 0, 255));
pixels.setPixelColor(3, pixels.Color(255, 255, 255));
if (preferences.getBool("ledTestOnPower", true))
{
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
pixels.setPixelColor(2, pixels.Color(0, 0, 255));
pixels.setPixelColor(3, pixels.Color(255, 255, 255));
}
else
{
pixels.clear();
}
pixels.show();
setupLedTask();
}
void setupLedTask()
{
ledTaskQueue = xQueueCreate(5, sizeof(char));
ledTaskQueue = xQueueCreate(2, sizeof(char));
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
}
@ -207,7 +237,6 @@ void setLights(uint32_t color)
pixels.show();
}
QueueHandle_t getLedTaskQueue()
{
return ledTaskQueue;

View file

@ -19,6 +19,10 @@ const int LED_FLASH_UPDATE = 2;
const int LED_FLASH_BLOCK_NOTIFY = 3;
const int LED_EFFECT_START_TIMER = 4;
const int LED_EFFECT_PAUSE_TIMER = 5;
const int LED_EFFECT_WIFI_WAIT_FOR_CONFIG = 100;
const int LED_EFFECT_WIFI_CONNECTING = 101;
const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
extern TaskHandle_t ledTaskHandle;

View file

@ -20,7 +20,7 @@ void setupWebserver()
}
// send event with message "hello!", id current millis
// and set reconnect delay to 1 second
eventSourceUpdate();
client->send("welcome",NULL,millis(),1000);
});
server.addHandler(&events);
@ -58,15 +58,15 @@ void setupWebserver()
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
server.begin();
if (!MDNS.begin(getMyHostname()))
{
Serial.println(F("Error setting up MDNS responder!"));
while (1)
{
delay(1000);
}
}
MDNS.addService("http", "tcp", 80);
// if (!MDNS.begin(getMyHostname()))
// {
// Serial.println(F("Error setting up MDNS responder!"));
// while (1)
// {
// delay(1000);
// }
// }
// MDNS.addService("http", "tcp", 80);
xTaskCreate(eventSourceTask, "eventSourceTask", 4096, NULL, tskIDLE_PRIORITY, &eventSourceTaskHandle);
}

View file

@ -1,9 +1,9 @@
#pragma once
#include "WebServer.h"
#include "ESPAsyncWebServer.h"
#include <ArduinoJson.h>
#include <LittleFS.h>
#include <ESPmDNS.h>
// #include <ESPmDNS.h>
#include "lib/block_notify.hpp"
#include "lib/price_notify.hpp"