diff --git a/.gitignore b/.gitignore index a4938ce5..95b48960 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .git .pio data/* +src/user_setups/active/* src/user_config_override.h platformio_override.ini diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 32ddcfd5..ea4bb8d1 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -7,40 +7,82 @@ #define HASP_USE_APP 1 -/* Network */ -#define HASP_HAS_NETWORK (ARDUINO_ARCH_ESP32>0 || ARDUINO_ARCH_ESP8266>0) +/* Network Services */ +#define HASP_HAS_NETWORK (ARDUINO_ARCH_ESP32 > 0 || ARDUINO_ARCH_ESP8266 > 0) +#ifndef HASP_USE_OTA #define HASP_USE_OTA (HASP_HAS_NETWORK) -#define HASP_USE_WIFI (HASP_HAS_NETWORK) -#define HASP_USE_MQTT (HASP_HAS_NETWORK) -#define HASP_USE_HTTP (HASP_HAS_NETWORK) -#define HASP_USE_MDNS (HASP_HAS_NETWORK) -#define HASP_USE_SYSLOG (HASP_HAS_NETWORK) -#define HASP_USE_TELNET (HASP_HAS_NETWORK) - -/* Filesystem */ -#define HASP_HAS_FILESYSTEM (ARDUINO_ARCH_ESP32>0 || ARDUINO_ARCH_ESP8266>0) - -#define HASP_USE_SPIFFS (HASP_HAS_FILESYSTEM) -#define HASP_USE_EEPROM 1 -#define HASP_USE_SDCARD 0 - -#define HASP_USE_GPIO 1 - -#define HASP_USE_QRCODE 1 -#define HASP_USE_PNGDECODE 0 - -#define HASP_NUM_INPUTS 3 // Buttons -#define HASP_NUM_OUTPUTS 3 - -#if defined(ARDUINO_ARCH_ESP32) -#define HASP_NUM_PAGES 12 -#else -#define HASP_NUM_PAGES 4 #endif +#ifndef HASP_USE_WIFI +#define HASP_USE_WIFI (HASP_HAS_NETWORK) +#endif -#if HASP_USE_SPIFFS>0 +#ifndef HASP_USE_MQTT +#define HASP_USE_MQTT 1 +#endif + +#ifndef HASP_USE_HTTP +#define HASP_USE_HTTP 1 +#endif + +#ifndef HASP_USE_MDNS +#define HASP_USE_MDNS (HASP_HAS_NETWORK) +#endif + +#ifndef HASP_USE_SYSLOG +#define HASP_USE_SYSLOG (HASP_HAS_NETWORK) +#endif + +#ifndef HASP_USE_TELNET +#define HASP_USE_TELNET 0 +#endif + +/* Filesystem */ +#define HASP_HAS_FILESYSTEM (ARDUINO_ARCH_ESP32 > 0 || ARDUINO_ARCH_ESP8266 > 0) + +#ifndef HASP_USE_SPIFFS +#define HASP_USE_SPIFFS (HASP_HAS_FILESYSTEM) +#endif + +#ifndef HASP_USE_EEPROM +#define HASP_USE_EEPROM 1 +#endif + +#ifndef HASP_USE_SDCARD +#define HASP_USE_SDCARD 0 +#endif + +#ifndef HASP_USE_GPIO +#define HASP_USE_GPIO 1 +#endif + +#ifndef HASP_USE_QRCODE +#define HASP_USE_QRCODE 1 +#endif + +#ifndef HASP_USE_PNGDECODE +#define HASP_USE_PNGDECODE 0 +#endif + +#ifndef HASP_NUM_INPUTS +#define HASP_NUM_INPUTS 3 // Buttons +#endif + +#ifndef HASP_NUM_OUTPUTS +#define HASP_NUM_OUTPUTS 3 +#endif + +#ifndef HASP_NUM_PAGES +#if defined(ARDUINO_ARCH_ESP8266) +#define HASP_NUM_PAGES 4 +#else +#define HASP_NUM_PAGES 12 +#endif +#endif + +/* Includes */ +#if HASP_USE_SPIFFS > 0 #if defined(ARDUINO_ARCH_ESP32) #include "SPIFFS.h" #endif @@ -48,52 +90,56 @@ #include "hasp_spiffs.h" #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) -// #include "lv_zifont.h" -#endif +#include "lv_zifont.h" #endif +#endif // SPIFFS -#if HASP_USE_EEPROM>0 +#if HASP_USE_EEPROM > 0 #include "hasp_eeprom.h" #endif -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 #include "hasp_wifi.h" #endif -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 #include "hasp_mqtt.h" #endif -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 #include "hasp_http.h" #endif -#if HASP_USE_TELNET>0 +#if HASP_USE_TELNET > 0 #include "hasp_telnet.h" #endif -#if HASP_USE_MDNS>0 +#if HASP_USE_MDNS > 0 #include "hasp_mdns.h" #endif -#if HASP_USE_BUTTON>0 +#if HASP_USE_BUTTON > 0 #include "hasp_button.h" #endif -#if HASP_USE_OTA>0 +#if HASP_USE_OTA > 0 #include "hasp_ota.h" #endif -#if HASP_USE_TASMOTA_SLAVE>0 +#if HASP_USE_TASMOTA_SLAVE > 0 #include "hasp_slave.h" #endif -#if HASP_USE_ETHERNET>0 +#if HASP_USE_ETHERNET > 0 #include "hasp_ethernet.h" #endif -#endif - #ifndef FPSTR #define FPSTR(pstr_pointer) (reinterpret_cast(pstr_pointer)) #endif + +#ifndef PGM_P +#define PGM_P const char * +#endif + +#endif // HASP_CONF_H \ No newline at end of file diff --git a/include/stm32f4/hal_conf_custom.h b/include/stm32f4/hal_conf_custom.h new file mode 100644 index 00000000..0febc31b --- /dev/null +++ b/include/stm32f4/hal_conf_custom.h @@ -0,0 +1,13 @@ +/* Include the normal default core configuration */ +#include "stm32f4xx_hal_conf_default.h" + +/* Remove the default PHY address */ +#ifdef LAN8742A_PHY_ADDRESS +#undef LAN8742A_PHY_ADDRESS +#endif + +/* Section 2: PHY configuration section */ +/* Redefine LAN8742A PHY Address*/ +#ifndef LAN8742A_PHY_ADDRESS +#define LAN8742A_PHY_ADDRESS 0x01U //HASP_PHY_ADDRESS +#endif \ No newline at end of file diff --git a/lib/lvgl b/lib/lvgl index 21f52a93..5f739643 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 21f52a939133d91acc82a3a98767d35de4e2d7a5 +Subproject commit 5f739643f4b22254f5742504fcda3b7de50fb88b diff --git a/platformio.ini b/platformio.ini index 84f3a1a8..472aea04 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,6 +22,8 @@ extra_configs = default_envs = ; Uncomment the needed environments in platformio_override.ini ; You can also create new environments in in platformio_override.ini + DevEBox_STM32F4xx + black_f407vg ${override.extra_default_envs} ; -- Location of the configuration files @@ -93,6 +95,7 @@ stm32_flags= -D IRAM_ATTR= ; No IRAM_ATTR available on STM32 -D STM32 -D STREAMUTILS_USE_EEPROM_UPDATE=1 ; update cell only when changed + -D MQTT_MAX_PACKET_SIZE=2048 ; longer PubSubClient messages ; -- By default there are no ${override.build_flags} set ; -- to use it, copy platformio_override.ini from the template @@ -196,9 +199,10 @@ build_flags = -D HASP_OUTPUT_PIN=PA1 ; User LED D2 on DevEBox board -D HASP_INPUT_PIN=PA0 ; User Button K1 on DevEBox board -D STM32_SERIAL1 ; Set this option to use Serial1 as default sersial port, leave out if using Serial2 + -D USE_BUILTIN_ETHERNET=1 -D HASP_USE_ETHERNET=1 -D HAL_ETH_MODULE_ENABLED=1 - -D LAN8742A_PHY_ADDRESS=0x01U + ;-D LAN8742A_PHY_ADDRESS=0x01U ; Moved to include\stm32f4\hal_conf_custom.h ; -D DP83848_PHY_ADDRESS=0x01U lib_deps = @@ -208,6 +212,7 @@ lib_deps = ; STM32duino STM32Ethernet@^1.0.5 https://github.com/stm32duino/LwIP.git https://github.com/stm32duino/STM32Ethernet.git + EthernetWebServer_STM32 src_filter = +<*> -<.git/> -<.svn/> - - - - - + diff --git a/src/hasp_config.cpp b/src/hasp_config.cpp index 3e62e41f..ba6b14cb 100644 --- a/src/hasp_config.cpp +++ b/src/hasp_config.cpp @@ -206,6 +206,7 @@ void configWriteConfig() Log.verbose(F("WIFI: Settings changed")); writefile = true; } +#endif #if HASP_USE_MQTT if(settings[F("mqtt")].as().isNull()) settings.createNestedObject(F("mqtt")); changed = mqttGetConfig(settings[F("mqtt")]); @@ -240,7 +241,6 @@ void configWriteConfig() configOutput(settings[F("http")]); writefile = true; } -#endif #endif if(settings[F("debug")].as().isNull()) settings.createNestedObject(F("debug")); @@ -350,6 +350,7 @@ void configSetup() #if HASP_USE_WIFI Log.verbose(F("Loading WiFi settings")); wifiSetConfig(settings[F("wifi")]); +#endif #if HASP_USE_MQTT Log.verbose(F("Loading MQTT settings")); mqttSetConfig(settings[F("mqtt")]); @@ -366,8 +367,7 @@ void configSetup() Log.verbose(F("Loading HTTP settings")); httpSetConfig(settings[F("http")]); #endif -#endif // Wifi - // } + // } Log.notice(F("User configuration loaded")); } //#endif diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index 7255a41c..38a2d271 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -161,14 +161,13 @@ void dispatchDim(String strDimLevel) // Set the current state if(strDimLevel.length() != 0) guiSetDim(strDimLevel.toInt()); dispatchPrintln(F("DIM"), strDimLevel); + char buffer[8]; #if HASP_USE_MQTT > 0 - char buffer[8]; itoa(guiGetDim(), buffer, DEC); mqtt_send_state(F("dim"), buffer); #endif #if HASP_USE_TASMOTA_SLAVE > 0 - char buffer[8]; itoa(guiGetDim(), buffer, DEC); slave_send_state(F("dim"), buffer); #endif diff --git a/src/hasp_ethernet.cpp b/src/hasp_ethernet.cpp index 8c30ab9b..c61f1f10 100644 --- a/src/hasp_ethernet.cpp +++ b/src/hasp_ethernet.cpp @@ -22,11 +22,16 @@ void ethernetSetup() IPAddress ip = Ethernet.localIP(); Log.notice(F("ETH: DHCP Success got IP=%d.%d.%d.%d"),ip[0], ip[1], ip[2], ip[3]); } + + uint8_t *mac; + mac = Ethernet.MACAddress(); + Log.notice(F("ETH: MAC Address %x:%x:%x:%x:%x:%x"),*mac,*(mac+1),*(mac+2),*(mac+3),*(mac+4),*(mac+5)); + } void ethernetLoop(void) { - Ethernet.maintain(); + Ethernet.maintain(); } diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 76c9d8e6..917af85a 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -41,6 +41,11 @@ File pFileOut; #endif uint8_t guiSnapshot = 0; +#if defined(STM32F4xx) +//#include +// EthernetWebServer * webClient(0); +#endif + #if defined(ARDUINO_ARCH_ESP8266) #include ESP8266WebServer * webClient; // for snatshot @@ -75,7 +80,7 @@ static uint8_t guiRotation = TFT_ROTATION; #if ESP32 > 0 || ESP8266 > 0 static Ticker tick; /* timer for interrupt handler */ #else -static Ticker tick(lv_tick_handler,guiTickPeriod); +static Ticker tick(lv_tick_handler, guiTickPeriod); #endif static TFT_eSPI tft; // = TFT_eSPI(); /* TFT instance */ static uint16_t calData[5] = {0, 65535, 0, 65535, 0}; @@ -171,14 +176,15 @@ static bool guiCheckSleep() /* Flush VDB bytes to a stream */ static void gui_take_screenshot(uint8_t * data_p, size_t len) { -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) size_t res = 0; switch(guiSnapshot) { +#if HASP_USE_SPIFFS > 0 case 1: res = pFileOut.write(data_p, len); break; +#endif case 2: - res = webClient->client().write(data_p, len); + res = httpClientWrite(data_p, len); break; default: res = 0; // nothing to do @@ -186,7 +192,6 @@ static void gui_take_screenshot(uint8_t * data_p, size_t len) if(res != len) { Log.warning(F("GUI: Pixelbuffer not completely sent")); } -#endif } /* Experimetnal Display flushing */ @@ -197,7 +202,6 @@ static void IRAM_ATTR tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * are /* Update TFT */ tft.startWrite(); /* Start new TFT transaction */ tft.setWindow(area->x1, area->y1, area->x2, area->y2); /* set the working window */ - tft.setSwapBytes(true); /* set endianess */ tft.pushPixels((uint16_t *)color_p, len); /* Write words at once */ tft.endWrite(); /* terminate TFT transaction */ @@ -617,11 +621,12 @@ void guiSetup() { /* TFT init */ tft.begin(); + tft.setSwapBytes(true); /* set endianess */ #ifdef USE_DMA_TO_TFT -// DMA - should work with STM32F2xx/F4xx/F7xx processors -// NOTE: >>>>>> DMA IS FOR SPI DISPLAYS ONLY <<<<<< -tft.initDMA(); // Initialise the DMA engine (tested with STM32F446 and STM32F767) + // DMA - should work with STM32F2xx/F4xx/F7xx processors + // NOTE: >>>>>> DMA IS FOR SPI DISPLAYS ONLY <<<<<< + tft.initDMA(); // Initialise the DMA engine (tested with STM32F446 and STM32F767) #endif tft.setRotation(guiRotation); /* 1/3=Landscape or 0/2=Portrait orientation */ @@ -652,10 +657,10 @@ tft.initDMA(); // Initialise the DMA engine (tested with STM32F446 and STM32F767 #else static lv_disp_buf_t disp_buf; static lv_color_t guiVdbBuffer1[16 * 512u]; // 16 KBytes - static lv_color_t guiVdbBuffer2[16 * 512u]; // 16 KBytes + // static lv_color_t guiVdbBuffer2[16 * 512u]; // 16 KBytes guiVDBsize = sizeof(guiVdbBuffer1) / sizeof(guiVdbBuffer1[0]); - lv_disp_buf_init(&disp_buf, guiVdbBuffer1, guiVdbBuffer2, guiVDBsize); - //lv_disp_buf_init(&disp_buf, guiVdbBuffer1, NULL, guiVDBsize); + // lv_disp_buf_init(&disp_buf, guiVdbBuffer1, guiVdbBuffer2, guiVDBsize); + lv_disp_buf_init(&disp_buf, guiVdbBuffer1, NULL, guiVDBsize); #endif /* Initialize PNG decoder */ @@ -781,27 +786,27 @@ tft.initDMA(); // Initialise the DMA engine (tested with STM32F446 and STM32F767 tick.attach_ms(guiTickPeriod, lv_tick_handler); #else -/* -#if defined(TIM1) - TIM_TypeDef * Instance = TIM1; -#else - TIM_TypeDef * Instance = TIM2; -#endif -*/ + /* + #if defined(TIM1) + TIM_TypeDef * Instance = TIM1; + #else + TIM_TypeDef * Instance = TIM2; + #endif + */ // Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() // function is finished. - /* static HardwareTimer * MyTim = new HardwareTimer(Instance); - MyTim->pause(); - MyTim->setPrescaleFactor(1); - MyTim->setMode(0, TIMER_OUTPUT_COMPARE, NC); - MyTim->setOverflow(1000 * guiTickPeriod, MICROSEC_FORMAT); // MicroSec - MyTim->setCount(0,MICROSEC_FORMAT); - MyTim->refresh(); - MyTim->detachInterrupt(); - MyTim->attachInterrupt((void (*)(HardwareTimer *))lv_tick_handler); - MyTim->detachInterrupt(0); - MyTim->attachInterrupt(0,(void (*)(HardwareTimer *))lv_tick_handler); - MyTim->resume();*/ + /* static HardwareTimer * MyTim = new HardwareTimer(Instance); + MyTim->pause(); + MyTim->setPrescaleFactor(1); + MyTim->setMode(0, TIMER_OUTPUT_COMPARE, NC); + MyTim->setOverflow(1000 * guiTickPeriod, MICROSEC_FORMAT); // MicroSec + MyTim->setCount(0,MICROSEC_FORMAT); + MyTim->refresh(); + MyTim->detachInterrupt(); + MyTim->attachInterrupt((void (*)(HardwareTimer *))lv_tick_handler); + MyTim->detachInterrupt(0); + MyTim->attachInterrupt(0,(void (*)(HardwareTimer *))lv_tick_handler); + MyTim->resume();*/ tick.start(); #endif @@ -816,14 +821,13 @@ void IRAM_ATTR guiLoop() tick.update(); #endif - //lv_tick_handler(); + // lv_tick_handler(); lv_task_handler(); /* let the GUI do its work */ guiCheckSleep(); #if TOUCH_DRIVER == 1 touch.loop(); #endif - } void guiStop() @@ -969,14 +973,15 @@ bool guiSetConfig(const JsonObject & settings) } if(calData[0] != 0 || calData[1] != 65535 || calData[2] != 0 || calData[3] != 65535) { - Log.trace(F("calData set [%u, %u, %u, %u, %u]"), calData[0], calData[1], calData[2], calData[3],calData[4]); + Log.trace(F("calData set [%u, %u, %u, %u, %u]"), calData[0], calData[1], calData[2], calData[3], + calData[4]); oobeSetAutoCalibrate(false); } else { Log.notice(F("First Touch Calibration enabled")); oobeSetAutoCalibrate(true); } - - if (status) tft.setTouch(calData); + + if(status) tft.setTouch(calData); changed |= status; } @@ -991,23 +996,15 @@ static void guiSetBmpHeader(uint8_t * buffer_p, int32_t data) *buffer_p++ = (data >> 24) & 0xFF; } -#if defined(ARDUINO_ARCH_ESP8266) static void guiSendBmpHeader(); -void guiTakeScreenshot(ESP8266WebServer & client) -#endif -#if defined(ARDUINO_ARCH_ESP32) - static void guiSendBmpHeader(); - -void guiTakeScreenshot(WebServer & client) -#endif // ESP32{ -#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +void guiTakeScreenshot() { - webClient = &client; - lv_disp_t * disp = lv_disp_get_default(); + // webClient = &client; + // lv_disp_t * disp = lv_disp_get_default(); - webClient->setContentLength(122 + disp->driver.hor_res * disp->driver.ver_res * sizeof(lv_color_t)); - webClient->send(200, PSTR("image/bmp"), ""); + // webClient->setContentLength(122 + disp->driver.hor_res * disp->driver.ver_res * sizeof(lv_color_t)); + // webClient->send(200, PSTR("image/bmp"), ""); guiSnapshot = 2; guiSendBmpHeader(); @@ -1068,15 +1065,17 @@ static void guiSendBmpHeader() buffer[70 + 0] = 0x20; if(guiSnapshot == 1) { +#if HASP_USE_SPIFFS > 0 size_t len = pFileOut.write(buffer, 122); if(len != sizeof(buffer)) { Log.warning(F("GUI: Data written does not match header size")); } else { Log.verbose(F("GUI: Bitmap header written")); } +#endif } else if(guiSnapshot == 2) { - if(webClient->client().write(buffer, 122) != 122) { + if(httpClientWrite(buffer, 122) != 122) { Log.warning(F("GUI: Data sent does not match header size")); } else { Log.verbose(F("GUI: Bitmap header sent")); @@ -1093,6 +1092,7 @@ static void guiSendBmpHeader() * @param[in] pFileName Output binary file name. * **/ +#if HASP_USE_SPIFFS > 0 void guiTakeScreenshot(const char * pFileName) { pFileOut = SPIFFS.open(pFileName, "w"); diff --git a/src/hasp_gui.h b/src/hasp_gui.h index f6f0618f..76166eae 100644 --- a/src/hasp_gui.h +++ b/src/hasp_gui.h @@ -6,15 +6,17 @@ #include "lvgl.h" -#if defined(ARDUINO_ARCH_ESP8266) -#include -void guiTakeScreenshot(ESP8266WebServer & client); -#endif +// #if defined(ARDUINO_ARCH_ESP8266) +// #include +// void guiTakeScreenshot(ESP8266WebServer & client); +// #endif -#if defined(ARDUINO_ARCH_ESP32) -#include -void guiTakeScreenshot(WebServer & client); -#endif // ESP32 +// #if defined(ARDUINO_ARCH_ESP32) +// #include +// void guiTakeScreenshot(WebServer & client); +// #endif // ESP32 + +void guiTakeScreenshot(); void guiSetup(); void guiLoop(void); diff --git a/src/hasp_hal.cpp b/src/hasp_hal.cpp index 672e7ba5..5a9536a6 100644 --- a/src/hasp_hal.cpp +++ b/src/hasp_hal.cpp @@ -1,10 +1,17 @@ -#if defined(ESP32) || defined(ESP8266) -#include +#if defined(STM32F4xx) +#include #endif #include "hasp_hal.h" -#if ESP32 +#if defined(ESP8266) +#include +#include +#endif + +#if defined(ESP32) +#include +#include #include "esp_system.h" #endif @@ -107,8 +114,6 @@ String halGetResetInfo() #endif } - - String halGetCoreVersion() { #if defined(ARDUINO_ARCH_ESP32) @@ -155,13 +160,12 @@ String halGetChipModel() return model; } - /*******************************/ /* Memory Management Functions */ #if defined(STM32F4xx) -#include // for mallinfo() -#include // for sbrk() +#include // for mallinfo() +#include // for sbrk() int freeHighMemory() { @@ -177,29 +181,29 @@ int freeHighMemory() #endif /* -extern char *fake_heap_end; // current heap start -extern char *fake_heap_start; // current heap end +extern char *fake_heap_end; // current heap start +extern char *fake_heap_start; // current heap end -char* getHeapStart() { - return fake_heap_start; -} - -char* getHeapEnd() { - return (char*)sbrk(0); -} - -char* getHeapLimit() { - return fake_heap_end; +char* getHeapStart() { + return fake_heap_start; } -int getMemUsed() { // returns the amount of used memory in bytes - struct mallinfo mi = mallinfo(); - return mi.uordblks; -} +char* getHeapEnd() { + return (char*)sbrk(0); +} -int getMemFree() { // returns the amount of free memory in bytes - struct mallinfo mi = mallinfo(); - return mi.fordblks + freeHighMemory(); +char* getHeapLimit() { + return fake_heap_end; +} + +int getMemUsed() { // returns the amount of used memory in bytes + struct mallinfo mi = mallinfo(); + return mi.uordblks; +} + +int getMemFree() { // returns the amount of free memory in bytes + struct mallinfo mi = mallinfo(); + return mi.fordblks + freeHighMemory(); } */ size_t halGetMaxFreeBlock() @@ -239,3 +243,57 @@ uint8_t halGetHeapFragmentation() return (int8_t)(100.00f - (float)freeHighMemory() * 100.00f / (float)halGetFreeHeap()); #endif } + +String halGetMacAddress(int start, const char * seperator) +{ + byte mac[6]; + +#if defined(STM32F4xx) + uint8_t * mac_p; + mac_p = Ethernet.MACAddress(); + for(uint8_t i = 0; i < 6; i++) mac[i] = *(mac_p + i); +#else + WiFi.macAddress(mac); +#endif + + String cMac((char *)0); + cMac.reserve(32); + + for(int i = start; i < 6; ++i) { + if(mac[i] < 0x10) cMac += "0"; + cMac += String(mac[i], HEX); + if(i < 5) cMac += seperator; + } + cMac.toUpperCase(); + return cMac; +} + +uint16_t halGetCpuFreqMHz() +{ +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_32) + return ESP.getCpuFreqMHz(); +#else + return (F_CPU / 1000 / 1000); +#endif +} + +String halFormatBytes(size_t bytes) +{ + String output((char *)0); + output.reserve(128); + + if(bytes < 1024) { + output += bytes; + } else if(bytes < (1024 * 1024)) { + output += bytes / 1024.0; + output += "K"; + } else if(bytes < (1024 * 1024 * 1024)) { + output += bytes / 1024.0 / 1024.0; + output += "M"; + } else { + output += bytes / 1024.0 / 1024.0 / 1024.0; + output += "G"; + } + output += "B"; + return output; +} \ No newline at end of file diff --git a/src/hasp_hal.h b/src/hasp_hal.h index 97f85f0a..9cdbef18 100644 --- a/src/hasp_hal.h +++ b/src/hasp_hal.h @@ -10,5 +10,8 @@ size_t halGetMaxFreeBlock(void); size_t halGetFreeHeap(void); String halGetCoreVersion(void); String halGetChipModel(); +String halGetMacAddress(int start, const char * seperator); +uint16_t halGetCpuFreqMHz(void); +String halFormatBytes(size_t bytes); #endif \ No newline at end of file diff --git a/src/hasp_http.cpp b/src/hasp_http.cpp index 0b35fb4b..2d6b2dbd 100644 --- a/src/hasp_http.cpp +++ b/src/hasp_http.cpp @@ -1,430 +1,3 @@ -#if 0 - -#include "Arduino.h" -#include "ArduinoJson.h" -#include "ArduinoLog.h" -//#include "Update.h" -#include "lvgl.h" - -#include "hasp_conf.h" - -#include "hasp_gui.h" -#include "hasp_hal.h" -#include "hasp_debug.h" -#include "hasp_mqtt.h" -#include "hasp_wifi.h" -#include "hasp_spiffs.h" -#include "hasp_config.h" -#include "hasp_dispatch.h" -#include "hasp.h" - -#ifdef ESP32 -#include -#include -#elif defined(ESP8266) -#include -#include -#endif -#include - -AsyncWebServer webServer(80); - -#if defined(ARDUINO_ARCH_ESP32) -#include "SPIFFS.h" -#endif -#include -#include - -bool httpEnable = true; -bool webServerStarted = false; -uint16_t httpPort = 80; -FS * filesystem = &SPIFFS; -File fsUploadFile; -char httpUser[32] = ""; -char httpPassword[32] = ""; -// HTTPUpload * upload; -#define HTTP_PAGE_SIZE (6 * 256) - -const char MAIN_MENU_BUTTON[] PROGMEM = - "

"; -const char MIT_LICENSE[] PROGMEM = "
MIT License

"; - -const char HTTP_DOCTYPE[] PROGMEM = - ""; -const char HTTP_META_GO_BACK[] PROGMEM = ""; -const char HTTP_HEADER[] PROGMEM = "%s"; -const char HTTP_STYLE[] PROGMEM = - ""; -const char HTTP_SCRIPT[] PROGMEM = ""; -const char HTTP_HEADER_END[] PROGMEM = - "
"; - -// Additional CSS style to match Hass theme -const char HASP_STYLE[] PROGMEM = - ""; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -// URL for auto-update "version.json" -const char UPDATE_URL[] PROGMEM = "http://haswitchplate.com/update/version.json"; -// Default link to compiled Arduino firmware image -String espFirmwareUrl = "http://haswitchplate.com/update/HASwitchPlate.ino.d1_mini.bin"; -// Default link to compiled Nextion firmware images -String lcdFirmwareUrl = "http://haswitchplate.com/update/HASwitchPlate.tft"; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -String getOption(int value, String label, bool selected) -{ - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR(""), value, - (selected ? PSTR(" selected") : ""), label.c_str()); - return buffer; -} -String getOption(String value, String label, bool selected) -{ - char buffer[128]; - snprintf_P(buffer, sizeof(buffer), PSTR(""), value.c_str(), - (selected ? PSTR(" selected") : ""), label.c_str()); - return buffer; -} - -bool httpIsAuthenticated(AsyncWebServerRequest * request, const String & page) -{ - if(httpPassword[0] != '\0') { // Request HTTP auth if httpPassword is set - if(!request->authenticate(httpUser, httpPassword)) { - request->requestAuthentication(); - return false; - } - } - - char buffer[128]; - snprintf(buffer, sizeof(buffer), PSTR("HTTP: Sending %s page to client connected from: %s"), page.c_str(), - request->client()->remoteIP().toString().c_str()); - debugPrintln(buffer); - return true; -} - -void webSendFooter(AsyncResponseStream * response) -{ - response->print(F("")); -} - -void webHandleRoot(AsyncWebServerRequest * request) -{ - if(!httpIsAuthenticated(request, F("root"))) return; - AsyncResponseStream * response = request->beginResponseStream("text/html"); - - String nodename((char *)0); - nodename.reserve(128); - nodename = httpGetNodename(); - - response->print(F("

")); - response->print(nodename); - response->print(F("


")); - - response->print(F("

")); - response->print( - F("

")); - response->print(F("

")); - - response->print( - F("

")); - - if(SPIFFS.exists(F("/edit.htm.gz"))) { - response->print(F("

")); - } - - response->print( - F("

")); - - webSendFooter(response); - request->send(response); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void webHandleHaspConfig(AsyncWebServerRequest * request) -{ // http://plate01/config/http - if(!httpIsAuthenticated(request, F("config/hasp"))) return; - AsyncResponseStream * response = request->beginResponseStream("text/html"); - - DynamicJsonDocument settings(256); - haspGetConfig(settings.to()); - - String nodename((char *)0); - nodename.reserve(128); - nodename = httpGetNodename(); - - response->print(F("

")); - response->print(nodename); - response->print(F("


")); - - response->print(F("

")); - response->print(F("


")); - - response->print(F("
")); - response->print(F("

UI Theme (required)
")); - response->print( - F("Hue

")); - response->print(F("

Default Font

")); - - response->print(F("

Startup Layout (optional)
Startup Page (required)

Startup Brightness (required)

")); - - response->print(F("

")); - - response->print( - F("

")); - - webSendFooter(response); - request->send(response); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void webHandleScreenshot(AsyncWebServerRequest * request) -{ // http://plate01/screenshot - if(!httpIsAuthenticated(request, F("screenshot"))) return; - - if(request->hasArg(F("q"))) { - guiTakeScreenshot(request); - } else { - AsyncResponseStream * response = request->beginResponseStream("text/html"); - - String nodename((char *)0); - nodename.reserve(128); - nodename = httpGetNodename(); - - response->print(F("

")); - response->print(nodename); - response->print(F("


")); - - response->print(F("

")); - response->print(F("

print(F("el=document.getElementById('bmp');el.src='?q='+timestamp;return false;\">")); - response->print(F("

")); - // response->print( FPSTR(MAIN_MENU_BUTTON); - - webSendFooter(response); - request->send(response); - } -} -//////////////////////////////////////////////////////////////////////////////////////////////////// -void httpHandleNotFound(AsyncWebServerRequest * request) -{ // webServer 404 - // if(handleFileRead(webServer.uri())) return; - - debugPrintln(String(F("HTTP: Sending 404 to client connected from: ")) + request->client()->remoteIP().toString()); - - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - - httpMessage += F("File Not Found\n\nURI: "); - httpMessage += request->url(); - httpMessage += F("\nMethod: "); - httpMessage += (request->method() == HTTP_GET) ? F("GET") : F("POST"); - httpMessage += F("\nArguments: "); - httpMessage += request->args(); - httpMessage += "\n"; - for(uint8_t i = 0; i < request->args(); i++) { - httpMessage += " " + request->argName(i) + ": " + request->arg(i) + "\n"; - } - request->send(404, F("text/plain"), httpMessage); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void webHandleSaveConfig() -{ - // if(!httpIsAuthenticated(F("saveConfig"))) return; - - configWriteConfig(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void webHandleFirmware() -{ - // if(!httpIsAuthenticated(F("firmware"))) return; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void httpSetup() -{ - if(WiFi.getMode() != WIFI_STA) { - debugPrintln(F("HTTP: Wifi access point")); - // webServer.on(F("/"), webHandleWifiConfig); - } else { - - webServer.on(String(F("/")).c_str(), HTTP_GET, webHandleRoot); - webServer.on(String(F("/config/hasp")).c_str(), webHandleHaspConfig); - webServer.on(String(F("/screenshot")).c_str(), webHandleScreenshot); - - webServer.onNotFound(httpHandleNotFound); - - webServer.begin(); - - httpReconnect(); - debugPrintln(F("HTTP: Setup Complete")); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void httpReconnect() -{ - if(!httpEnable) return; - - if(webServerStarted) { - webServer.end(); - webServerStarted = false; - debugPrintln(F("HTTP: Server stoped")); - } else if(WiFi.status() == WL_CONNECTED || WiFi.getMode() != WIFI_STA) { - - /* - if(WiFi.getMode() != WIFI_STA) { - webServer.on(F("/"), webHandleWifiConfig); - webServer.on(F("/config"), webHandleConfig); - webServer.onNotFound(httpHandleNotFound); - } else { - } - */ - webServer.begin(); - webServerStarted = true; - - debugPrintln(String(F("HTTP: Server started @ http://")) + - (WiFi.getMode() != WIFI_STA ? WiFi.softAPIP().toString() : WiFi.localIP().toString())); - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void httpLoop() -{ - // if(httpEnable) webServer.handleClient(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void httpEverySecond() -{ - if(httpEnable && !webServerStarted) httpReconnect(); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -bool httpGetConfig(const JsonObject & settings) -{ - settings[FPSTR(F_CONFIG_ENABLE)] = httpEnable; - settings[FPSTR(F_CONFIG_PORT)] = httpPort; - settings[FPSTR(F_CONFIG_USER)] = httpUser; - settings[FPSTR(F_CONFIG_PASS)] = httpPassword; - - configOutput(settings); - return true; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -bool httpSetConfig(const JsonObject & settings) -{ - configOutput(settings); - bool changed = false; - - changed |= configSet(httpPort, settings[FPSTR(F_CONFIG_PORT)], PSTR("httpPort")); - - if(!settings[FPSTR(F_CONFIG_USER)].isNull()) { - changed |= strcmp(httpUser, settings[FPSTR(F_CONFIG_USER)]) != 0; - strncpy(httpUser, settings[FPSTR(F_CONFIG_USER)], sizeof(httpUser)); - } - - if(!settings[FPSTR(F_CONFIG_PASS)].isNull()) { - changed |= strcmp(httpPassword, settings[FPSTR(F_CONFIG_PASS)]) != 0; - strncpy(httpPassword, settings[FPSTR(F_CONFIG_PASS)], sizeof(httpPassword)); - } - - return changed; -} - -#else - //#include "webServer.h" #include "Arduino.h" #include "ArduinoJson.h" @@ -432,7 +5,7 @@ bool httpSetConfig(const JsonObject & settings) #include "lvgl.h" #include "StringStream.h" -#ifdef ESP32 +#if defined(ARDUINO_ARCH_ESP32) #include "Update.h" #endif @@ -457,18 +30,26 @@ bool httpSetConfig(const JsonObject & settings) #include #endif -#if HASP_USE_HTTP>0 +#if HASP_USE_HTTP > 0 bool httpEnable = true; bool webServerStarted = false; uint16_t httpPort = 80; -FS * filesystem = &SPIFFS; + +#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) +FS * filesystem = &SPIFFS; File fsUploadFile; +#endif + char httpUser[32] = ""; char httpPassword[32] = ""; -HTTPUpload * upload; #define HTTP_PAGE_SIZE (6 * 256) +#if defined(STM32F4xx) +#include +EthernetWebServer webServer(80); +#endif + #if defined(ARDUINO_ARCH_ESP8266) #include ESP8266WebServer webServer(80); @@ -477,9 +58,10 @@ ESP8266WebServer webServer(80); #if defined(ARDUINO_ARCH_ESP32) #include WebServer webServer(80); - #endif // ESP32 +HTTPUpload * upload; + const char MAIN_MENU_BUTTON[] PROGMEM = "

"; const char MIT_LICENSE[] PROGMEM = "
MIT License

"; @@ -551,10 +133,14 @@ bool httpIsAuthenticated(const __FlashStringHelper * page) } } - { - Log.verbose(F("HTTP: Sending %s page to client connected from: %s"), page, - webServer.client().remoteIP().toString().c_str()); - } +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + Log.verbose(F("HTTP: Sending %s page to client connected from: %s"), page, + webServer.client().remoteIP().toString().c_str()); +#else + Log.verbose(F("HTTP: Sending %s page to client connected from: %s"), page, + String(webServer.client().remoteIP()).c_str()); +#endif + return true; } @@ -577,72 +163,100 @@ void webSendFooter() char buffer[128]; snprintf_P(buffer, sizeof(buffer), PSTR("%u.%u.%u"), HASP_VERSION_MAJOR, HASP_VERSION_MINOR, HASP_VERSION_REVISION); +#if defined(STM32F4xx) + webServer.sendContent(HTTP_END); + webServer.sendContent(buffer); + webServer.sendContent(HTTP_FOOTER); +#else webServer.sendContent_P(HTTP_END); webServer.sendContent(buffer); webServer.sendContent_P(HTTP_FOOTER); +#endif } void webSendPage(char * nodename, uint32_t httpdatalength, bool gohome = false) { - char buffer[64]; - snprintf_P(buffer, sizeof(buffer), PSTR("%u.%u.%u"), HASP_VERSION_MAJOR, HASP_VERSION_MINOR, HASP_VERSION_REVISION); + { + char buffer[64]; + snprintf_P(buffer, sizeof(buffer), PSTR("%u.%u.%u"), HASP_VERSION_MAJOR, HASP_VERSION_MINOR, + HASP_VERSION_REVISION); - /* Calculate Content Length upfront */ - uint16_t contentLength = strlen(buffer); // verion length - contentLength += sizeof(HTTP_DOCTYPE) - 1; - contentLength += sizeof(HTTP_HEADER) - 1 - 2 + strlen(nodename); - contentLength += sizeof(HTTP_SCRIPT) - 1; - contentLength += sizeof(HTTP_STYLE) - 1; - contentLength += sizeof(HASP_STYLE) - 1; - if(gohome) contentLength += sizeof(HTTP_META_GO_BACK) - 1; - contentLength += sizeof(HTTP_HEADER_END) - 1; - contentLength += sizeof(HTTP_END) - 1; - contentLength += sizeof(HTTP_FOOTER) - 1; + /* Calculate Content Length upfront */ + uint16_t contentLength = strlen(buffer); // verion length + contentLength += sizeof(HTTP_DOCTYPE) - 1; + contentLength += sizeof(HTTP_HEADER) - 1 - 2 + strlen(nodename); + contentLength += sizeof(HTTP_SCRIPT) - 1; + contentLength += sizeof(HTTP_STYLE) - 1; + contentLength += sizeof(HASP_STYLE) - 1; + if(gohome) contentLength += sizeof(HTTP_META_GO_BACK) - 1; + contentLength += sizeof(HTTP_HEADER_END) - 1; + contentLength += sizeof(HTTP_END) - 1; + contentLength += sizeof(HTTP_FOOTER) - 1; - if(httpdatalength > HTTP_PAGE_SIZE) { - Log.warning(F("HTTP: Sending page with %u static and %u dynamic bytes"), contentLength, httpdatalength); + if(httpdatalength > HTTP_PAGE_SIZE) { + Log.warning(F("HTTP: Sending page with %u static and %u dynamic bytes"), contentLength, httpdatalength); + } + + webServer.setContentLength(contentLength + httpdatalength); +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + webServer.send_P(200, PSTR("text/html"), HTTP_DOCTYPE); // 122 +#else + webServer.send(200, ("text/html"), HTTP_DOCTYPE); // 122 +#endif + + sprintf_P(buffer, HTTP_HEADER, nodename); + webServer.sendContent(buffer); // 17-2+len } - webServer.setContentLength(contentLength + httpdatalength); - webServer.send_P(200, PSTR("text/html"), HTTP_DOCTYPE); // 122 - sprintf_P(buffer, HTTP_HEADER, nodename); - webServer.sendContent(buffer); // 17-2+len +#if defined(STM32F4xx) + webServer.sendContent(HTTP_SCRIPT); // 131 + webServer.sendContent(HTTP_STYLE); // 487 + webServer.sendContent(HASP_STYLE); // 145 + if(gohome) webServer.sendContent(HTTP_META_GO_BACK); // 47 + webServer.sendContent(HTTP_HEADER_END); // 80 +#else webServer.sendContent_P(HTTP_SCRIPT); // 131 webServer.sendContent_P(HTTP_STYLE); // 487 webServer.sendContent_P(HASP_STYLE); // 145 if(gohome) webServer.sendContent_P(HTTP_META_GO_BACK); // 47 webServer.sendContent_P(HTTP_HEADER_END); // 80 +#endif } void webHandleRoot() { if(!httpIsAuthenticated(F("root"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("

"); - httpMessage += F("

"); - httpMessage += - PSTR("

"); + httpMessage += F("

"); + httpMessage += + F("

"); + httpMessage += + PSTR("

"); - httpMessage += - F("

"); + httpMessage += + F("

"); - if(SPIFFS.exists(F("/edit.htm.gz"))) { - httpMessage += F( - "

"); +#if HASP_USE_SPIFFS > 0 + if(SPIFFS.exists(F("/edit.htm.gz"))) { + httpMessage += F("

"); + } +#endif + + httpMessage += + F("

"); + + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); } - - httpMessage += - F("

"); - - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + // httpMessage.clear(); webSendFooter(); } @@ -651,16 +265,18 @@ void httpHandleReboot() { // http://plate01/reboot if(!httpIsAuthenticated(F("reboot"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); - httpMessage = F("Rebooting Device"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); + httpMessage = F("Rebooting Device"); - webSendPage(httpGetNodename(), httpMessage.length(), true); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), true); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); delay(200); @@ -692,30 +308,36 @@ void webHandleScreenshot() } if(webServer.hasArg(F("q"))) { - guiTakeScreenshot(webServer); + lv_disp_t * disp = lv_disp_get_default(); + webServer.setContentLength(122 + disp->driver.hor_res * disp->driver.ver_res * sizeof(lv_color_t)); + webServer.send(200, PSTR("image/bmp"), ""); + guiTakeScreenshot(); + webServer.client().stop(); + } else { + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + httpMessage += + F(""); + httpMessage += F("

"); + httpMessage += F( + "

"); + httpMessage += F("

"); + httpMessage += F("

"); + httpMessage += FPSTR(MAIN_MENU_BUTTON); - httpMessage += - F(""); - httpMessage += F("

"); - httpMessage += - F("

"); - httpMessage += F("

"); - httpMessage += F("

"); - httpMessage += FPSTR(MAIN_MENU_BUTTON); - - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } } @@ -726,44 +348,47 @@ void webHandleAbout() { // http://plate01/about if(!httpIsAuthenticated(F("about"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

HASP OpenHardware edition

Copyright© 2020 Francis Van Roie "); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

Based on the previous work of the following open source developers.


"); - httpMessage += F("

HASwitchPlate

Copyright© 2019 Allen Derusha allen@derusha.org"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += - F("

LittlevGL

Copyright© 2016 Gábor Kiss-Vámosi
Copyright© 2019 " - "LittlevGL"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

zi Font Engine

Copyright© 2020 Francis Van Roie"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

TFT_eSPI Library

Copyright© 2020 Bodmer (https://github.com/Bodmer) All " - "rights reserved.
FreeBSD License

"); - httpMessage += - F("

includes parts from the Adafruit_GFX library
Copyright© 2012 Adafruit Industries. " - "All rights reserved
BSD License

"); - httpMessage += F("

ArduinoJson

Copyright© 2014-2020 Benoit BLANCHON"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

PubSubClient

Copyright© 2008-2015 Nicholas O'Leary"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

ArduinoLog

Copyright© 2017,2018 Thijs Elenbaas, MrRobot62, rahuldeo2047, NOX73, " - "dhylands, Josha blemasle, mfalkvidd"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

Syslog

Copyright© 2016 Martin Sloup"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

QR Code generator

Copyright© Project Nayuki"); - httpMessage += FPSTR(MIT_LICENSE); - httpMessage += F("

AceButton

Copyright© 2018 Brian T. Park"); - httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

HASP OpenHardware edition

Copyright© 2020 Francis Van Roie "); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

Based on the previous work of the following open source developers.


"); + httpMessage += F("

HASwitchPlate

Copyright© 2019 Allen Derusha allen@derusha.org"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += + F("

LittlevGL

Copyright© 2016 Gábor Kiss-Vámosi
Copyright© 2019 " + "LittlevGL"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

zi Font Engine

Copyright© 2020 Francis Van Roie"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

TFT_eSPI Library

Copyright© 2020 Bodmer (https://github.com/Bodmer) All " + "rights reserved.
FreeBSD License

"); + httpMessage += + F("

includes parts from the Adafruit_GFX library
Copyright© 2012 Adafruit Industries. " + "All rights reserved
BSD License

"); + httpMessage += F("

ArduinoJson

Copyright© 2014-2020 Benoit BLANCHON"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

PubSubClient

Copyright© 2008-2015 Nicholas O'Leary"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += + F("

ArduinoLog

Copyright© 2017,2018 Thijs Elenbaas, MrRobot62, rahuldeo2047, NOX73, " + "dhylands, Josha blemasle, mfalkvidd"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

Syslog

Copyright© 2016 Martin Sloup"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

QR Code generator

Copyright© Project Nayuki"); + httpMessage += FPSTR(MIT_LICENSE); + httpMessage += F("

AceButton

Copyright© 2018 Brian T. Park"); + httpMessage += FPSTR(MIT_LICENSE); - httpMessage += FPSTR(MAIN_MENU_BUTTON); + httpMessage += FPSTR(MAIN_MENU_BUTTON); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } @@ -772,144 +397,160 @@ void webHandleInfo() { // http://plate01/ if(!httpIsAuthenticated(F("info"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - /* HASP Stats */ - httpMessage += F("HASP Version: "); - httpMessage += String(haspGetVersion()); - httpMessage += F("
Build DateTime: "); - httpMessage += __DATE__; - httpMessage += F(" "); - httpMessage += __TIME__; - httpMessage += F(" CET
Uptime: "); + /* HASP Stats */ + httpMessage += F("HASP Version: "); + httpMessage += String(haspGetVersion()); + httpMessage += F("
Build DateTime: "); + httpMessage += __DATE__; + httpMessage += F(" "); + httpMessage += __TIME__; + httpMessage += F(" CET
Uptime: "); - unsigned long time = millis() / 1000; - uint16_t day = time / 86400; - time = time % 86400; - uint8_t hour = time / 3600; - time = time % 3600; - uint8_t min = time / 60; - time = time % 60; - uint8_t sec = time; + unsigned long time = millis() / 1000; + uint16_t day = time / 86400; + time = time % 86400; + uint8_t hour = time / 3600; + time = time % 3600; + uint8_t min = time / 60; + time = time % 60; + uint8_t sec = time; - if(day > 0) { - httpMessage += String(day); - httpMessage += F("d "); - } - if(day > 0 || hour > 0) { - httpMessage += String(hour); - httpMessage += F("h "); - } - if(day > 0 || hour > 0 || min > 0) { - httpMessage += String(min); - httpMessage += F("m "); - } - httpMessage += String(sec); - httpMessage += F("s"); + if(day > 0) { + httpMessage += String(day); + httpMessage += F("d "); + } + if(day > 0 || hour > 0) { + httpMessage += String(hour); + httpMessage += F("h "); + } + if(day > 0 || hour > 0 || min > 0) { + httpMessage += String(min); + httpMessage += F("m "); + } + httpMessage += String(sec); + httpMessage += F("s"); - httpMessage += F("
Free Memory: "); - httpMessage += spiffsFormatBytes(ESP.getFreeHeap()); - httpMessage += F("
Memory Fragmentation: "); - httpMessage += String(halGetHeapFragmentation()); + httpMessage += F("
Free Memory: "); + httpMessage += halFormatBytes(halGetFreeHeap()); + httpMessage += F("
Memory Fragmentation: "); + httpMessage += String(halGetHeapFragmentation()); - /* LVGL Stats */ - lv_mem_monitor_t mem_mon; - lv_mem_monitor(&mem_mon); - httpMessage += F("

LVGL Memory: "); - httpMessage += spiffsFormatBytes(mem_mon.total_size); - httpMessage += F("
LVGL Free: "); - httpMessage += spiffsFormatBytes(mem_mon.free_size); - httpMessage += F("
LVGL Fragmentation: "); - httpMessage += mem_mon.frag_pct; + /* LVGL Stats */ + lv_mem_monitor_t mem_mon; + lv_mem_monitor(&mem_mon); + httpMessage += F("

LVGL Memory: "); + httpMessage += halFormatBytes(mem_mon.total_size); + httpMessage += F("
LVGL Free: "); + httpMessage += halFormatBytes(mem_mon.free_size); + httpMessage += F("
LVGL Fragmentation: "); + httpMessage += mem_mon.frag_pct; - // httpMessage += F("
LCD Model: ")) + String(LV_HASP_HOR_RES_MAX) + " x " + - // String(LV_HASP_VER_RES_MAX); httpMessage += F("
LCD Version: ")) + - // String(lcdVersion); - httpMessage += F("

LCD Active Page: "); - httpMessage += String(haspGetPage()); + // httpMessage += F("
LCD Model: ")) + String(LV_HASP_HOR_RES_MAX) + " x " + + // String(LV_HASP_VER_RES_MAX); httpMessage += F("
LCD Version: ")) + + // String(lcdVersion); + httpMessage += F("

LCD Active Page: "); + httpMessage += String(haspGetPage()); - /* Wifi Stats */ - httpMessage += F("

SSID: "); - httpMessage += String(WiFi.SSID()); - httpMessage += F("
Signal Strength: "); + /* Wifi Stats */ +#if HASP_USE_WIFI > 0 + httpMessage += F("

SSID: "); + httpMessage += String(WiFi.SSID()); + httpMessage += F("
Signal Strength: "); - int8_t rssi = WiFi.RSSI(); - httpMessage += String(rssi); - httpMessage += F("dBm ("); + int8_t rssi = WiFi.RSSI(); + httpMessage += String(rssi); + httpMessage += F("dBm ("); - if(rssi >= -50) { - httpMessage += F("Excellent)"); - } else if(rssi >= -60) { - httpMessage += F("Good)"); - } else if(rssi >= -70) { - httpMessage += F("Fair)"); - } else if(rssi >= -80) { - httpMessage += F("Weak)"); - } else { - httpMessage += F("Very Bad)"); - } + if(rssi >= -50) { + httpMessage += F("Excellent)"); + } else if(rssi >= -60) { + httpMessage += F("Good)"); + } else if(rssi >= -70) { + httpMessage += F("Fair)"); + } else if(rssi >= -80) { + httpMessage += F("Weak)"); + } else { + httpMessage += F("Very Bad)"); + } - httpMessage += F("
IP Address: "); - httpMessage += String(WiFi.localIP().toString()); - httpMessage += F("
Gateway: "); - httpMessage += String(WiFi.gatewayIP().toString()); - httpMessage += F("
DNS Server: "); - httpMessage += String(WiFi.dnsIP().toString()); - httpMessage += F("
MAC Address: "); - httpMessage += String(WiFi.macAddress()); + httpMessage += F("
IP Address: "); + httpMessage += String(WiFi.localIP().toString()); + httpMessage += F("
Gateway: "); + httpMessage += String(WiFi.gatewayIP().toString()); + httpMessage += F("
DNS Server: "); + httpMessage += String(WiFi.dnsIP().toString()); + httpMessage += F("
MAC Address: "); + httpMessage += String(WiFi.macAddress()); +#endif /* Mqtt Stats */ #if HASP_USE_MQTT > 0 - httpMessage += F("

MQTT Status: "); - if(mqttIsConnected()) { // Check MQTT connection - httpMessage += F("Connected"); - } else { - httpMessage += F("Disconnected, return code: "); - // +String(mqttClient.returnCode()); - } - httpMessage += F("
MQTT ClientID: "); + httpMessage += F("

MQTT Status: "); + if(mqttIsConnected()) { // Check MQTT connection + httpMessage += F("Connected"); + } else { + httpMessage += F("Disconnected, return code: "); + // +String(mqttClient.returnCode()); + } + httpMessage += F("
MQTT ClientID: "); - { - char mqttClientId[64]; - byte mac[6]; - WiFi.macAddress(mac); - snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%2x%2x%2x"), mqttNodeName, mac[3], mac[4], mac[5]); - httpMessage += mqttClientId; - } + { + char mqttClientId[64]; +#if HASP_USE_WIFI > 0 + byte mac[6]; + WiFi.macAddress(mac); + snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%02x%02x%02x"), mqttNodeName, mac[3], mac[4], + mac[5]); +#endif +#if HASP_USE_ETHERNET > 0 + uint8_t * mac; + mac = Ethernet.MACAddress(); + snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%02x%02x%02x"), mqttNodeName, *(mac + 3), + *(mac + 4), *(mac + 5)); +#endif + httpMessage += mqttClientId; + } +#endif // MQTT + + /* ESP Stats */ + httpMessage += F("

MCU Model: "); + httpMessage += halGetChipModel(); + httpMessage += F("
CPU Frequency: "); + httpMessage += String(halGetCpuFreqMHz()); + +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + httpMessage += F("MHz
Flash Chip Size: "); + httpMessage += halFormatBytes(ESP.getFlashChipSize()); + httpMessage += F("
Program Size: "); + httpMessage += halFormatBytes(ESP.getSketchSize()); + httpMessage += F("
Free Program Space: "); + httpMessage += halFormatBytes(ESP.getFreeSketchSpace()); #endif - /* ESP Stats */ - httpMessage += F("

MCU Model: "); - httpMessage += halGetChipModel(); - httpMessage += F("
CPU Frequency: "); - httpMessage += String(ESP.getCpuFreqMHz()); - httpMessage += F("MHz
Flash Chip Size: "); - httpMessage += spiffsFormatBytes(ESP.getFlashChipSize()); - httpMessage += F("
Program Size: "); - httpMessage += spiffsFormatBytes(ESP.getSketchSize()); - httpMessage += F("
Free Program Space: "); - httpMessage += spiffsFormatBytes(ESP.getFreeSketchSpace()); + //#if defined(ARDUINO_ARCH_ESP32) + // httpMessage += F("
ESP SDK version: "); + // httpMessage += String(ESP.getSdkVersion()); + //#else + httpMessage += F("
Core version: "); + httpMessage += String(halGetCoreVersion()); + //#endif + httpMessage += F("
Last Reset: "); + httpMessage += halGetResetInfo(); -#if defined(ARDUINO_ARCH_ESP32) - httpMessage += F("
ESP SDK version: "); - httpMessage += String(ESP.getSdkVersion()); -#else - httpMessage += F("
ESP Core version: "); - httpMessage += String(ESP.getCoreVersion()); -#endif - httpMessage += F("
Last Reset: "); - httpMessage += halGetResetInfo(); + httpMessage += FPSTR(MAIN_MENU_BUTTON); - httpMessage += FPSTR(MAIN_MENU_BUTTON); - - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } @@ -969,30 +610,6 @@ String getContentType(String filename) return encodedString; } */ -bool handleFileRead(String path) -{ - if(!httpIsAuthenticated(F("fileread"))) return false; - - path = webServer.urlDecode(path).substring(0, 31); - if(path.endsWith("/")) { - path += F("index.htm"); - } - String pathWithGz = path + F(".gz"); - if(filesystem->exists(pathWithGz) || filesystem->exists(path)) { - if(filesystem->exists(pathWithGz)) path += F(".gz"); - - File file = filesystem->open(path, "r"); - String contentType = getContentType(path); - if(path == F("/edit.htm.gz")) { - contentType = F("text/html"); - } - webServer.streamFile(file, contentType); - file.close(); - return true; - } - return false; -} - static unsigned long htppLastLoopTime = 0; void webUploadProgress() { @@ -1002,6 +619,7 @@ void webUploadProgress() } } +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) void webUpdatePrintError() { String output((char *)0); @@ -1015,16 +633,18 @@ void webUpdateReboot() { Log.notice(F("Update Success: %u bytes received. Rebooting..."), upload->totalSize); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); - httpMessage += F("Upload complete. Rebooting device, please wait..."); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); + httpMessage += F("Upload complete. Rebooting device, please wait..."); - webSendPage(httpGetNodename(), httpMessage.length(), true); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), true); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); delay(250); @@ -1059,6 +679,32 @@ void webHandleFirmwareUpdate() } } } +#endif + +#if HASP_USE_SPIFFS > 0 +bool handleFileRead(String path) +{ + if(!httpIsAuthenticated(F("fileread"))) return false; + + path = webServer.urlDecode(path).substring(0, 31); + if(path.endsWith("/")) { + path += F("index.htm"); + } + String pathWithGz = path + F(".gz"); + if(filesystem->exists(pathWithGz) || filesystem->exists(path)) { + if(filesystem->exists(pathWithGz)) path += F(".gz"); + + File file = filesystem->open(path, "r"); + String contentType = getContentType(path); + if(path == F("/edit.htm.gz")) { + contentType = F("text/html"); + } + webServer.streamFile(file, contentType); + file.close(); + return true; + } + return false; +} void handleFileUpload() { @@ -1123,7 +769,7 @@ void handleFileDelete() } filesystem->remove(path); webServer.send_P(200, mimetype, PSTR("")); - path.clear(); + // path.clear(); } void handleFileCreate() @@ -1188,7 +834,8 @@ void handleFileList() file = root.openNextFile(); } output += "]"; -#else + webServer.send(200, PSTR("text/json"), output); +#elif defined(ARDUINO_ARCH_ESP8266) Dir dir = filesystem->openDir(path); String output = "["; while(dir.next()) { @@ -1209,9 +856,10 @@ void handleFileList() entry.close(); } output += "]"; -#endif webServer.send(200, PSTR("text/json"), output); +#endif } +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// void webHandleConfig() @@ -1245,56 +893,65 @@ void webHandleConfig() // Password might have changed if(!httpIsAuthenticated(F("config"))) return; +#if HASP_USE_WIFI > 0 } else if(save == String(PSTR("wifi"))) { wifiSetConfig(settings.as()); +#endif } } } +// Reboot after saving wifi config in AP mode +#if HASP_USE_WIFI > 0 if(WiFi.getMode() != WIFI_STA) { httpHandleReboot(); } +#endif - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += - F("

"); +#if HASP_USE_WIFI > 0 + httpMessage += + F("

"); +#endif #if HASP_USE_MQTT > 0 - httpMessage += - F("

"); + httpMessage += + F("

"); #endif - httpMessage += - F("

"); + httpMessage += + F("

"); - httpMessage += - F("

"); + httpMessage += + F("

"); - httpMessage += - F("

"); + httpMessage += + F("

"); #if HASP_USE_GPIO > 0 - httpMessage += - F("

"); + httpMessage += + F("

"); #endif - httpMessage += - F("

"); + httpMessage += + F("

"); - httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += FPSTR(MAIN_MENU_BUTTON); - ; + httpMessage += FPSTR(MAIN_MENU_BUTTON); + ; - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } @@ -1307,41 +964,43 @@ void webHandleMqttConfig() DynamicJsonDocument settings(256); mqttGetConfig(settings.to()); - // char buffer[128]; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + // char buffer[128]; + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("
"); - httpMessage += F("HASP Node Name (required. lowercase letters, numbers, and _ only)" - "

Group Name (required)

MQTT Broker (required)
MQTT Port (required)
MQTT User (optional)
MQTT Password (optional)"); + httpMessage += F("HASP Node Name (required. lowercase letters, numbers, and _ only)" + "

Group Name (required)

MQTT Broker (required)
MQTT Port (required)
MQTT User (optional)
MQTT Password (optional)

"); - httpMessage += - PSTR("

"); + httpMessage += F("'>

"); + httpMessage += + PSTR("

"); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } #endif @@ -1351,70 +1010,71 @@ void webHandleGuiConfig() { // http://plate01/config/wifi if(!httpIsAuthenticated(F("config/gui"))) return; - DynamicJsonDocument settings(256); - guiGetConfig(settings.to()); + { + DynamicJsonDocument settings(256); + guiGetConfig(settings.to()); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("
"); + httpMessage += F(""); - httpMessage += F("

Short Idle

"); + httpMessage += F("

Short Idle

"); - httpMessage += F("

Long Idle

"); + httpMessage += F("

Long Idle

"); - int8_t rotation = settings[FPSTR(F_GUI_ROTATION)].as(); - httpMessage += F("

Orientation

"); + int8_t rotation = settings[FPSTR(F_GUI_ROTATION)].as(); + httpMessage += F("

Orientation

"); - int8_t bcklpin = settings[FPSTR(F_GUI_BACKLIGHTPIN)].as(); - httpMessage += F("

Backlight Control "); + httpMessage += getOption(-1, F("None"), bcklpin == -1); #if defined(ARDUINO_ARCH_ESP32) - httpMessage += getOption(5, F("GPIO 5"), bcklpin == 5); - httpMessage += getOption(16, F("GPIO 16"), bcklpin == 16); // D4 on ESP32 for D1 mini 32 - httpMessage += getOption(17, F("GPIO 17"), bcklpin == 17); - httpMessage += getOption(18, F("GPIO 18"), bcklpin == 18); - httpMessage += getOption(19, F("GPIO 19"), bcklpin == 19); - httpMessage += getOption(21, F("GPIO 21"), bcklpin == 21); - httpMessage += getOption(22, F("GPIO 22"), bcklpin == 22); - httpMessage += getOption(23, F("GPIO 23"), bcklpin == 23); + httpMessage += getOption(5, F("GPIO 5"), bcklpin == 5); + httpMessage += getOption(16, F("GPIO 16"), bcklpin == 16); // D4 on ESP32 for D1 mini 32 + httpMessage += getOption(17, F("GPIO 17"), bcklpin == 17); + httpMessage += getOption(18, F("GPIO 18"), bcklpin == 18); + httpMessage += getOption(19, F("GPIO 19"), bcklpin == 19); + httpMessage += getOption(21, F("GPIO 21"), bcklpin == 21); + httpMessage += getOption(22, F("GPIO 22"), bcklpin == 22); + httpMessage += getOption(23, F("GPIO 23"), bcklpin == 23); #else - httpMessage += getOption(5, F("D1 - GPIO 5"), bcklpin == 5); - httpMessage += getOption(4, F("D2 - GPIO 4"), bcklpin == 4); - httpMessage += getOption(0, F("D3 - GPIO 0"), bcklpin == 0); - httpMessage += getOption(2, F("D4 - GPIO 2"), bcklpin == 2); + httpMessage += getOption(5, F("D1 - GPIO 5"), bcklpin == 5); + httpMessage += getOption(4, F("D2 - GPIO 4"), bcklpin == 4); + httpMessage += getOption(0, F("D3 - GPIO 0"), bcklpin == 0); + httpMessage += getOption(2, F("D4 - GPIO 2"), bcklpin == 2); #endif - httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += PSTR("

"); + httpMessage += PSTR("

"); - httpMessage += - PSTR("

"); + httpMessage += + PSTR("

"); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } webSendFooter(); if(webServer.hasArg(F("action"))) dispatchCommand(webServer.arg(F("action"))); @@ -1446,10 +1106,12 @@ void webHandleWifiConfig() } httpMessage += F("'>

"); +#if HASP_USE_WIFI > 0 if(WiFi.getMode() == WIFI_STA) { httpMessage += PSTR("

"); } +#endif webSendPage(httpGetNodename(), httpMessage.length(), false); webServer.sendContent(httpMessage); @@ -1464,32 +1126,34 @@ void webHandleHttpConfig() { // http://plate01/config/http if(!httpIsAuthenticated(F("config/http"))) return; - DynamicJsonDocument settings(256); - httpGetConfig(settings.to()); + { + DynamicJsonDocument settings(256); + httpGetConfig(settings.to()); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("
"); - httpMessage += F("Web Username (optional)
Web Password (optional)"); + httpMessage += F("Web Username (optional)
Web Password (optional)

"); + + httpMessage += + PSTR("

"); + + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); } - httpMessage += F("'>

"); - - httpMessage += - PSTR("

"); - - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + // httpMessage.clear(); webSendFooter(); } #endif @@ -1502,33 +1166,36 @@ void webHandleGpioConfig() DynamicJsonDocument settings(256); debugGetConfig(settings.to()); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("
"); + httpMessage += F(""); - httpMessage += F(""); - httpMessage += F(""); - httpMessage += F(""); - httpMessage += F(""); - -for (uint8_t i=0; i"); + httpMessage += F(""); + httpMessage += F(""); httpMessage += F(""); -} - httpMessage += F("
PinTypeChannelNormalOptions
D1Button1HighOptions
D2Switch2HighOptions
D4Backligth15LowOptions
PinTypeChannelNormalOptions
D1Button1HighOptions
D2Switch2HighOptions
D4Backligth15LowOptions
"); + for(uint8_t i = 0; i < NUM_DIGITAL_PINS; i++) { + httpMessage += F("D4Backligth15LowOptions"); + } -// httpMessage += F("

"); + httpMessage += F(""); - httpMessage += - PSTR("

"); + // httpMessage += F("

"); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + httpMessage += + PSTR("

"); + + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } @@ -1540,55 +1207,57 @@ void webHandleDebugConfig() DynamicJsonDocument settings(256); debugGetConfig(settings.to()); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("
"); + httpMessage += F(""); - uint16_t baudrate = settings[FPSTR(F_CONFIG_BAUD)].as(); - httpMessage += F("

Serial Port

Telemetry Period (Seconds, 0=disable) " - "

"); + uint16_t baudrate = settings[FPSTR(F_CONFIG_BAUD)].as(); + httpMessage += F("

Serial Port

Telemetry Period (Seconds, 0=disable) " + "

"); - httpMessage += F("Syslog Hostame (optional)
Syslog Port (optional)
Syslog Port (optional) Syslog Facility "); + uint8_t logid = settings[FPSTR(F_CONFIG_LOG)].as(); + for(uint8_t i = 0; i < 8; i++) { + httpMessage += getOption(i, String(F("Local")) + i, i == logid); + } + + httpMessage += F("
Syslog Protocol () == 0) httpMessage += F(" checked"); + httpMessage += F(">IETF (RFC 5424)   () == 1) httpMessage += F(" checked"); + httpMessage += F(">BSD (RFC 3164)"); + + httpMessage += F("

"); + + httpMessage += + PSTR("

"); + + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); } - - httpMessage += F("
Syslog Protocol () == 0) httpMessage += F(" checked"); - httpMessage += F(">IETF (RFC 5424)   () == 1) httpMessage += F(" checked"); - httpMessage += F(">BSD (RFC 3164)"); - - httpMessage += F("

"); - - httpMessage += - PSTR("

"); - - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + // httpMessage.clear(); webSendFooter(); } @@ -1600,105 +1269,114 @@ void webHandleHaspConfig() DynamicJsonDocument settings(256); haspGetConfig(settings.to()); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("

"); - httpMessage += F("


"); + httpMessage += F("

"); + httpMessage += F("


"); - httpMessage += F("
"); - httpMessage += F("

UI Theme (required)"); - uint8_t themeid = settings[FPSTR(F_CONFIG_THEME)].as(); - httpMessage += getOption(0, F("Built-in"), themeid == 0); - httpMessage += getOption(8, F("Hasp"), themeid == 8); + uint8_t themeid = settings[FPSTR(F_CONFIG_THEME)].as(); + httpMessage += getOption(0, F("Built-in"), themeid == 0); + httpMessage += getOption(8, F("Hasp"), themeid == 8); #if LV_USE_THEME_ALIEN == 1 - httpMessage += getOption(1, F("Alien"), themeid == 1); + httpMessage += getOption(1, F("Alien"), themeid == 1); #endif #if LV_USE_THEME_NIGHT == 1 - httpMessage += getOption(2, F("Night"), themeid == 2); + httpMessage += getOption(2, F("Night"), themeid == 2); #endif #if LV_USE_THEME_MONO == 1 - httpMessage += getOption(3, F("Mono"), themeid == 3); + httpMessage += getOption(3, F("Mono"), themeid == 3); #endif #if LV_USE_THEME_MATERIAL == 1 - httpMessage += getOption(4, F("Material"), themeid == 4); + httpMessage += getOption(4, F("Material"), themeid == 4); #endif #if LV_USE_THEME_ZEN == 1 - httpMessage += getOption(5, F("Zen"), themeid == 5); + httpMessage += getOption(5, F("Zen"), themeid == 5); #endif #if LV_USE_THEME_NEMO == 1 - httpMessage += getOption(6, F("Nemo"), themeid == 6); + httpMessage += getOption(6, F("Nemo"), themeid == 6); #endif #if LV_USE_THEME_TEMPL == 1 - httpMessage += getOption(7, F("Template"), themeid == 7); + httpMessage += getOption(7, F("Template"), themeid == 7); #endif - httpMessage += F("
"); - httpMessage += - F("Hue

"); - httpMessage += F("

Default Font
"); + httpMessage += + F("Hue

"); + httpMessage += F("

Default Font

"); + httpMessage += F("

"); - httpMessage += F("

Startup Layout (optional)
Startup Page (required)

Startup Brightness (required)

"); + httpMessage += settings[FPSTR(F_CONFIG_PAGES)].as(); + httpMessage += F("'>
Startup Page (required)

Startup Brightness (required)

"); - httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += F("

"); + httpMessage += + F("

"); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void httpHandleNotFound() { // webServer 404 +#if HASP_USE_SPIFFS > 0 if(handleFileRead(webServer.uri())) return; +#endif +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) Log.notice(F("HTTP: Sending 404 to client connected from: %s"), webServer.client().remoteIP().toString().c_str()); +#else + Log.notice(F("HTTP: Sending 404 to client connected from: %s"), String(webServer.client().remoteIP()).c_str()); +#endif String httpMessage((char *)0); httpMessage.reserve(HTTP_PAGE_SIZE); @@ -1729,25 +1407,27 @@ void webHandleFirmware() { if(!httpIsAuthenticated(F("firmware"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("

"); - httpMessage += F("

"); + httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += F("

"); - httpMessage += F("

"); + httpMessage += F("

"); + httpMessage += F("

"); - httpMessage += FPSTR(MAIN_MENU_BUTTON); + httpMessage += FPSTR(MAIN_MENU_BUTTON); - webSendPage(httpGetNodename(), httpMessage.length(), false); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), false); + webServer.sendContent(httpMessage); + } + // httpMessage.clear(); webSendFooter(); } @@ -1756,18 +1436,20 @@ void httpHandleEspFirmware() { // http://plate01/espfirmware if(!httpIsAuthenticated(F("espfirmware"))) return; - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - httpMessage += F("

ESP update

Updating ESP firmware from: "); - httpMessage += webServer.arg("espFirmware"); + httpMessage += F("

ESP update

Updating ESP firmware from: "); + httpMessage += webServer.arg("espFirmware"); - webSendPage(httpGetNodename(), httpMessage.length(), true); - webServer.sendContent(httpMessage); - httpMessage.clear(); + webSendPage(httpGetNodename(), httpMessage.length(), true); + webServer.sendContent(httpMessage); + // httpMessage.clear(); + } webSendFooter(); Log.notice(F("HTTP: Attempting ESP firmware update from: %s"), webServer.arg("espFirmware").c_str()); @@ -1781,36 +1463,42 @@ void httpHandleResetConfig() bool resetConfirmed = webServer.arg(F("confirm")) == F("yes"); - String httpMessage((char *)0); - httpMessage.reserve(HTTP_PAGE_SIZE); - httpMessage += F("

"); - httpMessage += httpGetNodename(); - httpMessage += F("


"); + { + String httpMessage((char *)0); + httpMessage.reserve(HTTP_PAGE_SIZE); + httpMessage += F("

"); + httpMessage += httpGetNodename(); + httpMessage += F("


"); - if(resetConfirmed) { // User has confirmed, so reset everything - bool formatted = SPIFFS.format(); - if(formatted) { - httpMessage += F("Resetting all saved settings and restarting device into WiFi AP mode"); + if(resetConfirmed) { // User has confirmed, so reset everything +#if HASP_USE_SPIFFS > 0 + bool formatted = SPIFFS.format(); + if(formatted) { + httpMessage += F("Resetting all saved settings and restarting device into WiFi AP mode"); + } else { + httpMessage += F("Failed to format the internal flash partition"); + resetConfirmed = false; + } +#endif } else { - httpMessage += F("Failed to format the internal flash partition"); - resetConfirmed = false; + httpMessage += + F("

Warning

This process will reset all settings to the default values. The internal flash " + "will " + "be erased and the device is restarted. You may need to connect to the WiFi AP displayed on the " + "panel to " + "re-configure the device before accessing it again. ALL FILES WILL BE LOST!" + "


" + "

" + "


"); + + httpMessage += + PSTR("

"); } - } else { - httpMessage += - F("

Warning

This process will reset all settings to the default values. The internal flash will " - "be erased and the device is restarted. You may need to connect to the WiFi AP displayed on the panel to " - "re-configure the device before accessing it again. ALL FILES WILL BE LOST!" - "


" - "

" - "


"); - httpMessage += - PSTR("

"); + webSendPage(httpGetNodename(), httpMessage.length(), resetConfirmed); + webServer.sendContent(httpMessage); } - - webSendPage(httpGetNodename(), httpMessage.length(), resetConfirmed); - webServer.sendContent(httpMessage); - httpMessage.clear(); + // httpMessage.clear(); webSendFooter(); if(resetConfirmed) { @@ -1824,8 +1512,12 @@ void webStart() { webServer.begin(); webServerStarted = true; +#if HASP_USE_WIFI > 0 Log.notice(F("HTTP: Server started @ http://%s"), (WiFi.getMode() != WIFI_STA ? WiFi.softAPIP().toString().c_str() : WiFi.localIP().toString().c_str())); +#else + Log.notice(F("HTTP: Server started @ http://%s"), String(Ethernet.localIP()).c_str()); +#endif } void webStop() @@ -1840,10 +1532,12 @@ void httpSetup() { // httpSetConfig(settings); +#if HASP_USE_WIFI > 0 if(WiFi.getMode() != WIFI_STA) { Log.notice(F("HTTP: Wifi access point")); webServer.on(F("/"), webHandleWifiConfig); } else { +#endif webServer.on(F("/page/"), []() { String pageid = webServer.arg(F("page")); @@ -1851,6 +1545,7 @@ void httpSetup() haspSetPage(pageid.toInt()); }); +#if HASP_USE_SPIFFS > 0 webServer.on(F("/list"), HTTP_GET, handleFileList); // load editor webServer.on(F("/edit"), HTTP_GET, []() { @@ -1866,6 +1561,8 @@ void httpSetup() // second callback handles file uploads at that location webServer.on( F("/edit"), HTTP_POST, []() { webServer.send(200, "text/plain", ""); }, handleFileUpload); +#endif + // get heap status, analog input value and all GPIO statuses in one json call /*webServer.on(F("/all"), HTTP_GET, []() { String json; @@ -1902,12 +1599,16 @@ void httpSetup() webServer.on(F("/saveConfig"), webHandleSaveConfig); webServer.on(F("/resetConfig"), httpHandleResetConfig); webServer.on(F("/firmware"), webHandleFirmware); +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) webServer.on( F("/update"), HTTP_POST, []() { webServer.send(200, "text/plain", ""); }, webHandleFirmwareUpdate); webServer.on(F("/espfirmware"), httpHandleEspFirmware); +#endif webServer.on(F("/reboot"), httpHandleReboot); webServer.onNotFound(httpHandleNotFound); +#if HASP_USE_WIFI > 0 } +#endif // Shared pages webServer.on(F("/about"), webHandleAbout); @@ -1925,7 +1626,11 @@ void httpReconnect() if(webServerStarted) { webStop(); - } else if(WiFi.status() == WL_CONNECTED || WiFi.getMode() != WIFI_STA) { + } else +#if HASP_USE_WIFI > 0 + if(WiFi.status() == WL_CONNECTED || WiFi.getMode() != WIFI_STA) +#endif + { webStart(); } } @@ -1990,5 +1695,24 @@ bool httpSetConfig(const JsonObject & settings) return changed; } -#endif +size_t httpClientWrite(const uint8_t * buf, size_t size) +{ + /***** Sending 16Kb at once freezes on STM32 EthernetClient *****/ + size_t bytes_sent = 0; + while(bytes_sent < size) { + if(!webServer.client()) return bytes_sent; + if(size - bytes_sent >= 4096) { + bytes_sent += webServer.client().write(buf + bytes_sent, 4096); + } else { + bytes_sent += webServer.client().write(buf + bytes_sent, size - bytes_sent); + } + // Serial.println(bytes_sent); + + // stm32_eth_scheduler(); // already in write + // webServer.client().flush(); + delay(1); // Fixes the freeze + } + return bytes_sent; +} + #endif \ No newline at end of file diff --git a/src/hasp_http.h b/src/hasp_http.h index d7a17db5..3caf1b7f 100644 --- a/src/hasp_http.h +++ b/src/hasp_http.h @@ -9,6 +9,8 @@ void httpLoop(void); void httpEvery5Seconds(void); void httpReconnect(void); +size_t httpClientWrite(const uint8_t *buf, size_t size); // Screenshot Write Data + bool httpGetConfig(const JsonObject & settings); bool httpSetConfig(const JsonObject & settings); diff --git a/src/hasp_mqtt.cpp b/src/hasp_mqtt.cpp index eef09b2d..a9390dba 100644 --- a/src/hasp_mqtt.cpp +++ b/src/hasp_mqtt.cpp @@ -11,10 +11,15 @@ #if defined(ARDUINO_ARCH_ESP32) #include -#else +WiFiClient mqttNetworkClient; +#elif defined(ARDUINO_ARCH_ESP8266) #include #include #include +WiFiClient mqttNetworkClient; +#else +#include +EthernetClient mqttNetworkClient; #endif #include "hasp_hal.h" @@ -97,8 +102,7 @@ const String mqttLightSubscription = "hasp/" + String(haspGetNodename()) const String mqttLightBrightSubscription = "hasp/" + String(haspGetNodename()) + "/brightness/#"; */ -WiFiClient mqttWifiClient; -PubSubClient mqttClient(mqttWifiClient); +PubSubClient mqttClient(mqttNetworkClient); //////////////////////////////////////////////////////////////////////////////////////////////////// // Send changed values OUT @@ -179,11 +183,13 @@ void mqtt_send_statusupdate() snprintf_P(data, sizeof(data), PSTR("{\"status\":\"available\",\"version\":\"%s\",\"uptime\":%lu,"), haspGetVersion().c_str(), long(millis() / 1000)); strcat(buffer, data); +#if HASP_USE_WIFI snprintf_P(buffer, sizeof(buffer), PSTR("\"ssid\":\"%s\",\"rssi\":%i,\"ip\":\"%s\","), WiFi.SSID().c_str(), WiFi.RSSI(), WiFi.localIP().toString().c_str()); strcat(data, buffer); +#endif snprintf_P(buffer, sizeof(buffer), PSTR("\"heapFree\":%u,\"heapFrag\":%u,\"espCore\":\"%s\","), - ESP.getFreeHeap(), halGetHeapFragmentation(), halGetCoreVersion().c_str()); + halGetFreeHeap(), halGetHeapFragmentation(), halGetCoreVersion().c_str()); strcat(data, buffer); snprintf_P(buffer, sizeof(buffer), PSTR("\"espCanUpdate\":\"false\",\"page\":%u,\"numPages\":%u,"), haspGetPage(), (HASP_NUM_PAGES)); @@ -339,10 +345,18 @@ void mqttReconnect() bool mqttFirstConnect = true; { +#if HASP_USE_WIFI>0 byte mac[6]; WiFi.macAddress(mac); - snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%2x%2x%2x"), mqttNodeName, mac[3], mac[4], mac[5]); + snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%02x%02x%02x"), mqttNodeName, mac[3], mac[4], mac[5]); +#endif +#if HASP_USE_ETHERNET>0 + uint8_t * mac; + mac = Ethernet.MACAddress(); + snprintf_P(mqttClientId, sizeof(mqttClientId), PSTR("%s-%02x%02x%02x"), mqttNodeName, *(mac+3), *(mac+4), *(mac+5)); +#endif } + Log.verbose(mqttClientId); // Attempt to connect and set LWT and Clean Session snprintf_P(buffer, sizeof(buffer), PSTR("%sstatus"), mqttNodeTopic); @@ -537,7 +551,7 @@ bool mqttSetConfig(const JsonObject & settings) } // Prefill node name if(strlen(mqttNodeName) == 0) { - String mac = wifiGetMacAddress(3, ""); + String mac = halGetMacAddress(3, ""); mac.toLowerCase(); snprintf_P(mqttNodeName, sizeof(mqttNodeName), PSTR("plate_%s"), mac.c_str()); changed = true; diff --git a/src/hasp_spiffs.cpp b/src/hasp_spiffs.cpp index 8522b7f3..e4aeb2c3 100644 --- a/src/hasp_spiffs.cpp +++ b/src/hasp_spiffs.cpp @@ -102,25 +102,4 @@ void spiffsSetup() Log.verbose(F("FILE: SPI Flash FS mounted")); } #endif -} - -String spiffsFormatBytes(size_t bytes) -{ - String output((char *)0); - output.reserve(128); - - if(bytes < 1024) { - output += bytes; - } else if(bytes < (1024 * 1024)) { - output += bytes / 1024.0; - output += "K"; - } else if(bytes < (1024 * 1024 * 1024)) { - output += bytes / 1024.0 / 1024.0; - output += "M"; - } else { - output += bytes / 1024.0 / 1024.0 / 1024.0; - output += "G"; - } - output += "B"; - return output; } \ No newline at end of file diff --git a/src/hasp_spiffs.h b/src/hasp_spiffs.h index 39dbb956..c0dadaca 100644 --- a/src/hasp_spiffs.h +++ b/src/hasp_spiffs.h @@ -7,6 +7,5 @@ void spiffsSetup(void); void spiffsList(); void spiffsInfo(); -String spiffsFormatBytes(size_t bytes); #endif \ No newline at end of file diff --git a/src/hasp_telnet.cpp b/src/hasp_telnet.cpp index b59c2096..3c5eab43 100644 --- a/src/hasp_telnet.cpp +++ b/src/hasp_telnet.cpp @@ -12,8 +12,16 @@ #if defined(ARDUINO_ARCH_ESP32) #include -#else +WiFiClient telnetClient; +static WiFiServer * telnetServer; +#elif defined(ARDUINO_ARCH_ESP8266) #include +WiFiClient telnetClient; +static WiFiServer * telnetServer; +#else +#include +EthernetClient telnetClient; +static EthernetServer telnetServer(23); #endif #define TELNET_UNAUTHENTICATED 0 @@ -21,12 +29,14 @@ #define TELNET_USERNAME_NOK 99 #define TELNET_AUTHENTICATED 255 +#if HASP_USE_HTTP > 0 extern char httpUser[32]; extern char httpPassword[32]; +#endif uint8_t telnetLoginState = TELNET_UNAUTHENTICATED; -WiFiClient telnetClient; -static WiFiServer * telnetServer; +// WiFiClient telnetClient; +// static WiFiServer * telnetServer; uint16_t telnetPort = 23; bool telnetInCommandMode = false; uint8_t telnetEnabled = true; // Enable telnet debug output @@ -36,7 +46,7 @@ char telnetInputBuffer[128]; void telnetClientDisconnect() { - Log.notice(F("Closing session from %s"), telnetClient.remoteIP().toString().c_str()); + // Log.notice(F("Closing session from %s"), telnetClient.remoteIP().toString().c_str()); telnetClient.stop(); Log.unregisterOutput(1); // telnetClient telnetLoginState = TELNET_UNAUTHENTICATED; @@ -51,7 +61,7 @@ void telnetClientLogon() telnetLoginState = TELNET_AUTHENTICATED; // User and Pass are correct telnetLoginAttempt = 0; // Reset attempt counter Log.registerOutput(1, &telnetClient, LOG_LEVEL_VERBOSE, true); - Log.notice(F("Client login from %s"), telnetClient.remoteIP().toString().c_str()); + // Log.notice(F("Client login from %s"), telnetClient.remoteIP().toString().c_str()); telnetClient.flush(); /* Echo locally as separate string */ // telnetClient.print(F("TELNET: Client login from ")); @@ -66,17 +76,25 @@ void telnetAcceptClient() telnetClient.stop(); // client disconnected Log.unregisterOutput(1); // telnetClient } - telnetClient = telnetServer->available(); // ready for new client - Log.notice(F("Client connected from %s"), telnetClient.remoteIP().toString().c_str()); + telnetClient = telnetServer.available(); // ready for new client + // Log.notice(F("Client connected from %s"), telnetClient.remoteIP().toString().c_str()); + if(!telnetClient) { + Log.notice(F("Client NOT connected")); + return; + } + Log.notice(F("Client connected")); /* Avoid a buffer here */ telnetClient.print(0xFF); // DO TERMINAL-TYPE telnetClient.print(0xFD); telnetClient.print(0x1B); +#if HASP_USE_HTTP > 0 if(strlen(httpUser) != 0 || strlen(httpPassword) != 0) { telnetClient.print(F("\r\nUsername: ")); telnetLoginState = TELNET_UNAUTHENTICATED; - } else { + } else +#endif + { telnetClientLogon(); } telnetInputIndex = 0; // reset input buffer index @@ -100,6 +118,7 @@ static void telnetProcessLine() switch(telnetLoginState) { case TELNET_UNAUTHENTICATED: { telnetClient.printf(PSTR("Password: %c%c%c"), 0xFF, 0xFB, 0x01); // Hide characters +#if HASP_USE_HTTP > 0 telnetLoginState = strcmp(telnetInputBuffer, httpUser) == 0 ? TELNET_USERNAME_OK : TELNET_USERNAME_NOK; break; } @@ -112,13 +131,16 @@ static void telnetProcessLine() telnetLoginState = TELNET_UNAUTHENTICATED; telnetLoginAttempt++; // Subsequent attempt telnetClient.println(F("Authorization failed!\r\n")); - Log.warning(F("Incorrect login attempt from %s"), telnetClient.remoteIP().toString().c_str()); + // Log.warning(F("Incorrect login attempt from %s"), telnetClient.remoteIP().toString().c_str()); if(telnetLoginAttempt >= 3) { telnetClientDisconnect(); } else { telnetClient.print(F("Username: ")); } } +#else + telnetClientLogon(); +#endif break; } default: @@ -173,6 +195,15 @@ void telnetSetup() // telnetSetConfig(settings); if(telnetEnabled) { // Setup telnet server for remote debug output +#if defined(STM32F4xx) + // if(!telnetServer) telnetServer = new EthernetServer(telnetPort); + // if(telnetServer) { + telnetServer.begin(); + Log.notice(F("Debug telnet console started")); + // } else { + // Log.error(F("Failed to start telnet server")); + //} +#else if(!telnetServer) telnetServer = new WiFiServer(telnetPort); if(telnetServer) { telnetServer->setNoDelay(true); @@ -189,12 +220,41 @@ void telnetSetup() } else { Log.error(F("Failed to start telnet server")); } +#endif } } void IRAM_ATTR telnetLoop() { // Basic telnet client handling code from: https://gist.github.com/tablatronix/4793677ca748f5f584c95ec4a2b10303 +#if defined(STM32F4xx) +Ethernet.schedule(); + // if(telnetServer) + { // client is connected + EthernetClient client = telnetServer.available(); + if(client) { + if(!telnetClient || !telnetClient.connected()) { + //telnetAcceptClient(client); + + telnetClient = client; // ready for new client + // Log.notice(F("Client connected from %s"), telnetClient.remoteIP().toString().c_str()); + if(!telnetClient) { + Log.notice(F("Client NOT connected")); + return; + } + Log.notice(F("Client connected")); + + /* Avoid a buffer here */ + // telnetClient.print(0xFF); // DO TERMINAL-TYPE + // telnetClient.print(0xFD); + // telnetClient.print(0x1B); + + } else { + //client.stop(); // have client, block new connections + } + } + } +#else if(telnetServer && telnetServer->hasClient()) { // client is connected if(!telnetClient || !telnetClient.connected()) { telnetAcceptClient(); @@ -209,6 +269,7 @@ void IRAM_ATTR telnetLoop() telnetProcessCharacter(telnetClient.read()); // client input processing } } +#endif } bool telnetGetConfig(const JsonObject & settings) diff --git a/src/hasp_tft.cpp b/src/hasp_tft.cpp index 1f246d01..031b5f23 100644 --- a/src/hasp_tft.cpp +++ b/src/hasp_tft.cpp @@ -3,6 +3,7 @@ #include "TFT_eSPI.h" #include "hasp_tft.h" +#include "hasp_hal.h" #if defined(ARDUINO_ARCH_ESP8266) ADC_MODE(ADC_VCC); // tftShowConfig measures the voltage on the pin @@ -84,11 +85,10 @@ void tftShowConfig(TFT_eSPI & tft) Log.verbose(F("TFT: TFT_eSPI : v%s"), tftSetup.version.c_str()); #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_32) Log.verbose(F("TFT: Processor : ESP%x"), tftSetup.esp); - Log.verbose(F("TFT: CPU freq. : %i MHz"), ESP.getCpuFreqMHz()); #else Log.verbose(F("TFT: Processor : STM%x"), tftSetup.esp); - Log.verbose(F("TFT: CPU freq. : %i MHz"), F_CPU / 1000 / 1000); #endif + Log.verbose(F("TFT: CPU freq. : %i MHz"), halGetCpuFreqMHz()); #if defined(ARDUINO_ARCH_ESP8266) Log.verbose(F("TFT: Voltage : %2.2f V"), ESP.getVcc() / 918.0); // 918 empirically determined diff --git a/src/hasp_wifi.cpp b/src/hasp_wifi.cpp index ecde60b0..2921b027 100644 --- a/src/hasp_wifi.cpp +++ b/src/hasp_wifi.cpp @@ -41,22 +41,6 @@ uint8_t wifiReconnectCounter = 0; // const byte DNS_PORT = 53; // DNSServer dnsServer; -String wifiGetMacAddress(int start, const char * seperator) -{ - byte mac[6]; - WiFi.macAddress(mac); - String cMac((char *)0); - cMac.reserve(32); - - for(int i = start; i < 6; ++i) { - if(mac[i] < 0x10) cMac += "0"; - cMac += String(mac[i], HEX); - if(i < 5) cMac += seperator; - } - cMac.toUpperCase(); - return cMac; -} - void wifiConnected(IPAddress ipaddress) { Log.notice(F("WIFI: Received IP address %s"), ipaddress.toString().c_str()); diff --git a/src/main.cpp b/src/main.cpp index 934db777..75a3e146 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,10 @@ #include "hasp_oobe.h" #include "hasp_gpio.h" +#if HASP_USE_ETHERNET > 0 +#include +#endif + bool isConnected; uint8_t mainLoopCounter = 0; unsigned long mainLastLoopTime = 0; @@ -42,32 +46,19 @@ void setup() * Apply User Configuration ***************************/ debugSetup(); - gpioSetup(); #if HASP_USE_GPIO - guiSetup(); + gpioSetup(); #endif #if HASP_USE_WIFI wifiSetup(); #endif + + guiSetup(); oobeSetup(); haspSetup(); -#if HASP_USE_WIFI - -#if HASP_USE_HTTP - httpSetup(); -#endif - -#if HASP_USE_MQTT - mqttSetup(); -#endif - -#if HASP_USE_TELNET - telnetSetup(); -#endif - #if HASP_USE_MDNS mdnsSetup(); #endif @@ -76,12 +67,22 @@ void setup() otaSetup(); #endif -#endif // WIFI - -#if HASP_USE_ETHERNET +#if HASP_USE_ETHERNET > 0 ethernetSetup(); #endif +#if HASP_USE_MQTT + mqttSetup(); +#endif + +#if HASP_USE_HTTP + httpSetup(); +#endif + +#if HASP_USE_TELNET > 0 + telnetSetup(); +#endif + #if HASP_USE_TASMOTA_SLAVE slaveSetup(); #endif @@ -92,21 +93,21 @@ void setup() void loop() { /* Storage Loops */ -/* -#if HASP_USE_EEPROM - // eepromLoop(); // Not used -#endif + /* + #if HASP_USE_EEPROM + // eepromLoop(); // Not used + #endif -#if HASP_USE_SPIFFS - // spiffsLoop(); // Not used -#endif + #if HASP_USE_SPIFFS + // spiffsLoop(); // Not used + #endif -#if HASP_USE_SDCARD - // sdcardLoop(); // Not used -#endif + #if HASP_USE_SDCARD + // sdcardLoop(); // Not used + #endif - // configLoop(); // Not used -*/ + // configLoop(); // Not used + */ /* Graphics Loops */ // tftLoop(); @@ -120,7 +121,9 @@ void loop() #endif /* Network Services Loops */ -#if HASP_USE_WIFI +#if HASP_USE_ETHERNET > 0 + ethernetLoop(); +#endif #if HASP_USE_MQTT mqttLoop(); @@ -130,10 +133,6 @@ void loop() httpLoop(); #endif // HTTP -#if HASP_USE_TELNET - telnetLoop(); -#endif // TELNET - #if HASP_USE_MDNS mdnsLoop(); #endif // MDNS @@ -142,11 +141,9 @@ void loop() otaLoop(); #endif // OTA -#endif // WIFI - -#if HASP_USE_ETHERNET - ethernetLoop(); -#endif +#if HASP_USE_TELNET > 0 + telnetLoop(); +#endif // TELNET #if HASP_USE_TASMOTA_SLAVE slaveLoop(); @@ -163,17 +160,24 @@ void loop() debugEverySecond(); /* Run Every 5 Seconds */ -#if HASP_USE_WIFI if(mainLoopCounter == 0 || mainLoopCounter == 5) { +#if HASP_USE_WIFI > 0 isConnected = wifiEvery5Seconds(); -#if HASP_USE_HTTP +#endif + +#if HASP_USE_ETHERNET > 0 + isConnected = Ethernet.linkStatus() == LinkON; + Serial.print(Ethernet.linkStatus()); +#endif + +#if HASP_USE_HTTP > 0 httpEvery5Seconds(); #endif -#if HASP_USE_MQTT + +#if HASP_USE_MQTT > 0 mqttEvery5Seconds(isConnected); #endif } -#endif // Wifi /* Reset loop counter every 10 seconds */ if(mainLoopCounter >= 9) {