diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index 11418ebd..428baf09 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -1,4 +1,6 @@ #include "hasp_dispatch.h" +#include "hasp_config.h" +#include "hasp_debug.h" #include "hasp_mqtt.h" #include "hasp_http.h" #include "hasp_mdns.h" @@ -32,13 +34,15 @@ void IRAM_ATTR dispatchAttribute(String & strTopic, String & strPayload) } // valid page } } else if(strTopic == "page") { + dispatchPage(strPayload); } else if(strTopic == "dim") { + dispatchDim(strPayload); } } void IRAM_ATTR dispatchPage(String & strPageid) { - debugPrintln("PAGE:" + strPageid); + debugPrintln("PAGE: " + strPageid); if(strPageid.length() == 0) { String strPayload = String(haspGetPage()); @@ -48,10 +52,28 @@ void IRAM_ATTR dispatchPage(String & strPageid) } } +void dispatchDim(String & strDimLevel) +{ + debugPrintln("DIM: " + strDimLevel); + + if(strDimLevel.length() == 0) { + String strPayload = String(guiGetDim()); + mqttSendState("dim", strPayload.c_str()); + } else { + guiSetDim(strDimLevel.toInt()); + } +} + void IRAM_ATTR dispatchCommand(String cmnd) { debugPrintln("CMND: " + cmnd); + if(cmnd.startsWith(F("page ")) || cmnd.startsWith(F("page="))) { + cmnd = cmnd.substring(5, cmnd.length()); + dispatchPage(cmnd); + return; + } + if(cmnd == F("calibrate")) { guiCalibrate(); return; @@ -63,7 +85,7 @@ void IRAM_ATTR dispatchCommand(String cmnd) } if(cmnd == F("reboot") || cmnd == F("restart")) { - haspReboot(true); + dispatchReboot(true); return; } @@ -81,7 +103,7 @@ void IRAM_ATTR dispatchCommand(String cmnd) } } -void IRAM_ATTR dispatchJson(String & strPayload) +void dispatchJson(String & strPayload) { // Parse an incoming JSON array into individual commands if(strPayload.endsWith(",]")) { // Trailing null array elements are an artifact of older Home Assistant automations @@ -97,14 +119,7 @@ void IRAM_ATTR dispatchJson(String & strPayload) return; } - // Slow - // for(uint8_t i = 0; i < haspCommands.size(); i++) { - // dispatchCommand(haspCommands[i]); - //} - - // Get a reference to the root array JsonArray arr = haspCommands.as(); - // Fast for(JsonVariant command : arr) { dispatchCommand(command.as()); } @@ -113,4 +128,17 @@ void IRAM_ATTR dispatchJson(String & strPayload) void IRAM_ATTR dispatchIdle(const __FlashStringHelper * state) { mqttSendState(String(F("idle")).c_str(), String(state).c_str()); +} + +void dispatchReboot(bool saveConfig) +{ + mqttStop(); // Stop the MQTT Client first + if(saveConfig) configWriteConfig(); + debugStop(); + delay(250); + wifiStop(); + debugPrintln(F("CMND: Properly Rebooting the MCU now!")); + debugPrintln(F("-------------------------------------")); + ESP.restart(); + delay(5000); } \ No newline at end of file diff --git a/src/hasp_dispatch.h b/src/hasp_dispatch.h index 57d590e4..e55ef7f1 100644 --- a/src/hasp_dispatch.h +++ b/src/hasp_dispatch.h @@ -9,7 +9,11 @@ void dispatchLoop(void); void dispatchAttribute(String & strTopic, String & strPayload); void dispatchCommand(String cmnd); void dispatchJson(String & strPayload); + void dispatchPage(String & strPageid); +void dispatchDim(String & strDimLevel); + void dispatchIdle(const __FlashStringHelper * state); +void dispatchReboot(bool saveConfig); #endif \ No newline at end of file diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 75a98f0d..d2d6fe5d 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -6,9 +6,6 @@ #include "TFT_eSPI.h" -#if defined(ARDUINO_ARCH_ESP32) -//#include "png_decoder.h" -#endif #include "lv_zifont.h" #include "hasp_log.h" @@ -18,24 +15,43 @@ #include "hasp_gui.h" #include "hasp.h" -#if LV_USE_HASP_SPIFFS +#if HASP_USE_PNGDECODE != 0 +#include "png_decoder.h" +#endif + +#if HASP_USE_SPIFFS #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" #endif #include // Include the SPIFFS library #endif +#if defined(ARDUINO_ARCH_ESP8266) +#include +static ESP8266WebServer * webClient; // for snatshot +#endif + +#if defined(ARDUINO_ARCH_ESP32) +#include +static WebServer * webClient; // for snatshot +#endif // ESP32 + #define LVGL_TICK_PERIOD 30 // 30 -bool guiAutoCalibrate = true; -uint16_t guiSleepTime = 150; // 0.1 second resolution -bool guiSleeping = false; -uint8_t guiTickPeriod = 50; +#ifndef TFT_BCKL +#define TFT_BCKL -1 // No Backlight Control +#endif + +int8_t guiDimLevel = -1; +int8_t guiBacklightPin = TFT_BCKL; +bool guiAutoCalibrate = true; +uint16_t guiSleepTime = 150; // 0.1 second resolution +bool guiSleeping = false; +uint8_t guiTickPeriod = 50; static Ticker tick; /* timer for interrupt handler */ static TFT_eSPI tft = TFT_eSPI(); /* TFT instance */ static uint16_t calData[5] = {0, 65535, 0, 65535, 0}; -static WiFiClient webClient; // for snatshot static File pFileOut; static uint8_t guiSnapshot = 0; @@ -92,7 +108,7 @@ void tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * c break; case 2: // Send to remote client - if(webClient.write(pixel, i) != i) { + if(webClient->client().write(pixel, i) != i) { errorPrintln(F("GUI: %sPixelbuffer not completely sent")); } } @@ -109,7 +125,7 @@ void tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * c break; case 2: // Send to remote client - if(webClient.write(pixel, i) != i) { + if(webClient->client().write(pixel, i) != i) { errorPrintln(F("GUI: %sPixelbuffer not completely sent")); } } @@ -231,7 +247,7 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings) #if defined(ARDUINO_ARCH_ESP32) /* allocate on iram (or psram ?) */ - buffer_size = 1024 * 8; + buffer_size = 1024 * 24; static lv_color_t * guiVdbBuffer = (lv_color_t *)malloc(sizeof(lv_color_t) * buffer_size); static lv_disp_buf_t disp_buf; lv_disp_buf_init(&disp_buf, guiVdbBuffer, NULL, buffer_size); @@ -250,7 +266,9 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings) #endif /* Initialize PNG decoder */ - // png_decoder_init(); +#if HASP_USE_PNGDECODE != 0 + png_decoder_init(); +#endif /* Initialize the display driver */ lv_disp_drv_t disp_drv; @@ -319,7 +337,22 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings) lv_fs_if_init(); #endif - // guiLoop(); + /* Setup Backlight Control Pin */ + if(guiBacklightPin >= 0) { + char msg[128]; + sprintf(msg, PSTR("LVGL: Backlight Pin = %i"), guiBacklightPin); + debugPrintln(msg); + +#if defined(ARDUINO_ARCH_ESP32) + // configure LED PWM functionalitites + ledcSetup(0, 1000, 10); + // attach the channel to the GPIO to be controlled + pinMode(guiBacklightPin, OUTPUT); + ledcAttachPin(guiBacklightPin, 0); +#else + pinMode(guiBacklightPin, OUTPUT); +#endif + } } void IRAM_ATTR guiLoop() @@ -330,11 +363,33 @@ void IRAM_ATTR guiLoop() void guiStop() {} +void guiSetDim(uint8_t level) +{ + if(guiBacklightPin >= 0) { + guiDimLevel = level >= 0 ? level : 0; + guiDimLevel = guiDimLevel <= 100 ? guiDimLevel : 100; + +#if defined(ARDUINO_ARCH_ESP32) + ledcWrite(0, map(guiDimLevel, 0, 100, 0, 1023)); // ledChannel and value +#else + analogWrite(D1, map(guiDimLevel, 0, 100, 0, 1023)); +#endif + } else { + guiDimLevel = -1; + } +} + +int8_t guiGetDim() +{ + return guiDimLevel; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// bool guiGetConfig(const JsonObject & settings) { - settings[FPSTR(F_GUI_TICKPERIOD)] = guiTickPeriod; - settings[FPSTR(F_GUI_IDLEPERIOD)] = guiSleepTime; + settings[FPSTR(F_GUI_TICKPERIOD)] = guiTickPeriod; + settings[FPSTR(F_GUI_IDLEPERIOD)] = guiSleepTime; + settings[FPSTR(F_GUI_BACKLIGHTPIN)] = guiBacklightPin; JsonArray array = settings[FPSTR(F_GUI_CALIBRATION)].to(); for(int i = 0; i < 5; i++) { @@ -362,6 +417,15 @@ bool guiSetConfig(const JsonObject & settings) guiTickPeriod = settings[FPSTR(F_GUI_TICKPERIOD)].as(); } + if(!settings[FPSTR(F_GUI_BACKLIGHTPIN)].isNull()) { + if(guiBacklightPin != settings[FPSTR(F_GUI_BACKLIGHTPIN)].as()) { + debugPrintln(F("guiBacklightPin set")); + } + changed |= guiBacklightPin != settings[FPSTR(F_GUI_BACKLIGHTPIN)].as(); + + guiBacklightPin = settings[FPSTR(F_GUI_BACKLIGHTPIN)].as(); + } + if(!settings[FPSTR(F_GUI_IDLEPERIOD)].isNull()) { if(guiSleepTime != settings[FPSTR(F_GUI_IDLEPERIOD)].as()) { debugPrintln(F("guiSleepTime set")); @@ -430,9 +494,15 @@ void guiTakeScreenshot(const char * pFileName) pFileOut.close(); printf(("[Display] data flushed to %s", pFileName)); } -void guiTakeScreenshot(WiFiClient client) + +#if defined(ARDUINO_ARCH_ESP8266) +void guiTakeScreenshot(ESP8266WebServer & client) +#endif +#if defined(ARDUINO_ARCH_ESP32) + void guiTakeScreenshot(WebServer & client) +#endif // ESP32{ { - webClient = client; + webClient = &client; uint8_t bmpheader[138] = {0x42, 0x4D, 0x8A, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x20, 0x00, @@ -440,10 +510,10 @@ void guiTakeScreenshot(WiFiClient client) 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x42, 0x47, 0x52, 0x73}; - if(client.write(bmpheader, sizeof(bmpheader)) != sizeof(bmpheader)) { - Serial.println("Data sent does not match header size!"); + if(webClient->client().write(bmpheader, sizeof(bmpheader)) != sizeof(bmpheader)) { + errorPrintln(F("GUI: %sData sent does not match header size")); } else { - Serial.println("OK BMP Header sent!"); + debugPrintln(F("GUI: Bitmap header sent")); } guiSnapshot = 2; @@ -451,5 +521,5 @@ void guiTakeScreenshot(WiFiClient client) lv_refr_now(NULL); /* Will call our disp_drv.disp_flush function */ guiSnapshot = 0; - printf("[Display] data flushed to webclient"); + debugPrintln(F("GUI: Bitmap data flushed to webclient")); } diff --git a/src/hasp_gui.h b/src/hasp_gui.h index da1e6b18..cdbe5a2b 100644 --- a/src/hasp_gui.h +++ b/src/hasp_gui.h @@ -6,19 +6,25 @@ #include "lvgl.h" -#if defined(ARDUINO_ARCH_ESP32) -#include -#else -#include +#if defined(ARDUINO_ARCH_ESP8266) +#include +void guiTakeScreenshot(ESP8266WebServer & client); #endif +#if defined(ARDUINO_ARCH_ESP32) +#include +void guiTakeScreenshot(WebServer & client); +#endif // ESP32 + void guiSetup(TFT_eSPI & screen, JsonObject settings); void guiLoop(void); void guiStop(void); void guiCalibrate(); void guiTakeScreenshot(const char * pFileName); -void guiTakeScreenshot(WiFiClient client); + +void guiSetDim(uint8_t level); +int8_t guiGetDim(void); bool guiGetConfig(const JsonObject & settings); bool guiSetConfig(const JsonObject & settings); diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index 176371dd..b92c473e 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -231,12 +231,7 @@ void mqttCallback(char * topic, byte * payload, unsigned int length) if(strTopic == F("page")) { // '[...]/device/command/page' -m '1' == nextionSendCmd("page 1") dispatchPage(strPayload); } else if(strTopic == F("dim")) { // '[...]/device/command/page' -m '1' == nextionSendCmd("page 1") -#if defined(ARDUINO_ARCH_ESP32) - ledcWrite(0, map(strPayload.toInt(), 0, 100, 0, 1023)); // ledChannel and value -#else - analogWrite(D1, map(strPayload.toInt(), 0, 100, 0, 1023)); -#endif - + dispatchDim(strPayload); } else if(strTopic == F("json")) { // '[...]/device/command/json' -m '["dim=5", "page 1"]' = // nextionSendCmd("dim=50"), nextionSendCmd("page 1") dispatchJson(strPayload); // Send to nextionParseJson() @@ -250,12 +245,8 @@ void mqttCallback(char * topic, byte * payload, unsigned int length) } else { // espStartOta(strPayload); } - } else if(strTopic == F("reboot")) { // '[...]/device/command/reboot' == reboot microcontroller) - debugPrintln(F("MQTT: Rebooting device")); - dispatchCommand(F("reboot")); - } else if(strTopic == F("lcdreboot")) { // '[...]/device/command/lcdreboot' == reboot LCD panel) - debugPrintln(F("MQTT: Rebooting LCD")); - dispatchCommand(F("reboot")); + } else if(strTopic == F("reboot") || strTopic == F("lcdreboot")) { + dispatchReboot(true); } else if(strTopic == F("factoryreset")) { // '[...]/device/command/factoryreset' == clear all saved settings) // configClearSaved(); //} else if(strPayload == "") { // '[...]/device/command/p[1].b[4].txt' -m '' == diff --git a/src/main.cpp b/src/main.cpp index 1f2558ae..82f643fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,10 @@ +#include "hasp_conf.h" #include #include "ArduinoJson.h" + #include "TFT_eSPI.h" -#include "hasp_conf.h" - #include "hasp_debug.h" -#include "hasp_eeprom.h" #include "hasp_spiffs.h" #include "hasp_config.h" #include "hasp_tft.h" @@ -13,32 +12,42 @@ //#include "hasp_ota.h" #include "hasp.h" -#if LV_USE_HASP_SPIFFS +#if HASP_USE_SPIFFS #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" #endif #include // Include the SPIFFS library #endif -#if LV_USE_HASP_WIFI +#if HASP_USE_EEPROM +#include "hasp_eeprom.h" +#endif + +#if HASP_USE_WIFI #include "hasp_wifi.h" #endif -#if LV_USE_HASP_MQTT +#if HASP_USE_MQTT #include "hasp_mqtt.h" #endif -#if LV_USE_HASP_HTTP +#if HASP_USE_HTTP #include "hasp_http.h" #endif +#if HASP_USE_MDNS +#include "hasp_mdns.h" +#endif + bool isConnected; void setup() { /* Init Storage */ +#if HASP_USE_EEPROM eepromSetup(); -#if LV_USE_HASP_SPIFFS +#endif +#if HASP_USE_SPIFFS spiffsSetup(); #endif @@ -46,20 +55,7 @@ void setup() DynamicJsonDocument settings(1024); configSetup(settings); - if(!settings[F("pins")][F("TFT_BCKL")].isNull()) { - int8_t pin = settings[F("pins")][F("TFT_BCKL")].as(); -#if defined(ARDUINO_ARCH_ESP32) - if(pin >= 0) - // configure LED PWM functionalitites - ledcSetup(0, 5000, 10); - // attach the channel to the GPIO to be controlled - ledcAttachPin(pin, 0); -#else - pinMode(pin, OUTPUT); -#endif - } - -#if LV_USE_HASP_SDCARD +#if HASP_USE_SDCARD sdcardSetup(); #endif @@ -72,18 +68,18 @@ void setup() haspSetup(settings[F("hasp")]); /* Init Network Services */ -#if LV_USE_HASP_WIFI +#if HASP_USE_WIFI wifiSetup(settings[F("wifi")]); -#if LV_USE_HASP_MQTT +#if HASP_USE_MQTT mqttSetup(settings[F("mqtt")]); #endif -#if LV_USE_HASP_MDNS +#if HASP_USE_MDNS mdnsSetup(settings[F("mdns")]); #endif -#if LV_USE_HASP_HTTP +#if HASP_USE_HTTP httpSetup(settings[F("http")]); #endif @@ -94,9 +90,11 @@ void setup() void loop() { /* Storage Loops */ - // eepromLoop(); +#if HASP_USE_EEPROM + eepromLoop(); +#endif // spiffsLoop(); -#if LV_USE_HASP_SDCARD +#if HASP_USE_SDCARD // sdcardLoop(); #endif @@ -110,19 +108,19 @@ void loop() // haspLoop(); /* Network Services Loops */ -#if LV_USE_HASP_WIFI > 0 +#if HASP_USE_WIFI isConnected = wifiLoop(); -#if LV_USE_HASP_MQTT > 0 +#if HASP_USE_MQTT mqttLoop(isConnected); #endif -#if LV_USE_HASP_HTTP > 0 +#if HASP_USE_HTTP httpLoop(isConnected); #endif -#if LV_USE_HASP_MDNS > 0 - mdnsLoop(wifiIsConnected); +#if HASP_USE_MDNS + mdnsLoop(isConnected); #endif // otaLoop(wifiIsConnected);