diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e80666b..080e70d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,5 +3,8 @@ // for the documentation about the extensions.json format "recommendations": [ "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" ] } diff --git a/git_rev_macro.py b/git_rev_macro.py new file mode 100644 index 0000000..27728af --- /dev/null +++ b/git_rev_macro.py @@ -0,0 +1,8 @@ +import subprocess + +revision = ( + subprocess.check_output(["git", "rev-parse", "--short=10", "HEAD"]) + .strip() + .decode("utf-8") +) +print("-DGIT_REV='\"%s\"'" % revision) \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 7f0d797..3f9dfa9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,6 +8,10 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html +[platformio] +extra_configs = + wifi_credentials.ini + [env:d1_mini] platform = espressif8266 board = d1_mini @@ -15,27 +19,36 @@ board_build.filesystem = littlefs board_build.f_flash = 80000000L board_build.ldscript = eagle.flash.4m1m.ld +monitor_filters = esp8266_exception_decoder +monitor_speed = 115200 + upload_protocol = espota -upload_port = ESP_OTA.local +upload_port = 10.0.1.34 upload_flags= - --auth=UploadTheFlag + --auth=${wifi_cred.admin_password} build_flags= - -D SERIAL_DEBUG - -D DEVICE_NAME='"DE CTF Timer Prototype 1"' - -D WIFI_CLIENT - -D WIFI_SSID='"BND_Scanner_#42"' - -D WIFI_PASS='"5xMYkerbLMdrsSdF3hpy5DM9"' - ;-D WIFI_AP - ;-D WIFI_SSID='"Dark Emergency CTF Timer"' - ;-D WIFI_PASS='"CaptureTheFlag"' - -D FACTION_1_NAME='"GOF"' - -D FACTION_2_NAME='"MILIZ"' - -D FACTION_3_NAME='"KGG"' + !python git_rev_macro.py + -DSERIAL_DEBUG + -DREMOTE_DEBUG + -DWIFI_CLIENT + -DCAPTIVE + -DWIFI_AP_IP_GW=10,0,0,1 + -DADMIN_PASSWORD=${wifi_cred.admin_password} + -DWIFI_SSID=${wifi_cred.wifi_ssid} + -DWIFI_PASSWORD=${wifi_cred.wifi_password} + -DWIFI_AP_PASSWORD=${wifi_cred.wifi_ap_password} + -DDEVICE_NAME='"Dark Emergency Timer"' + -DFACTION_1_NAME='"GOF"' + -DFACTION_2_NAME='"MILIZ"' + -DFACTION_3_NAME='"KGG"' framework = arduino lib_deps = smougenot/TM1637@0.0.0-alpha+sha.9486982048 + joaolopesf/RemoteDebug @ ^2.1.2 me-no-dev/ESP Async WebServer @ ^1.2.3 sstaub/Ticker @ ^4.2.0 adafruit/Adafruit INA219 @ ^1.1.1 + robtillaart/I2C_EEPROM @ ^1.5.2 + me-no-dev/ESP Async WebServer @ ^1.2.3 diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..b2e9fcd --- /dev/null +++ b/src/common.h @@ -0,0 +1,38 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#define Q(x) #x +#define QUOTE(x) Q(x) + +// Module connection pins (ESP GPIO-Nums) +#define CLK 16 +#define DIO_FAC_1_7SEG 14 +#define DIO_FAC_2_7SEG 12 +#define DIO_FAC_3_7SEG 13 + +#define DIO_FAC_1_TRG 0 +#define DIO_FAC_2_TRG 2 +#define DIO_FAC_3_TRG 15 + +#ifndef HOST_NAME +#define HOST_NAME "DE_Timer_%06X" // Use printf-Formatting - Chip-ID (uin32_t) will be added +#endif + +#ifndef OTA_DELAY +#define OTA_DELAY 50 // ticks -> 10ms / tick +#endif + +#ifndef ADMIN_PASSWORD +#error "You need to define ADMIN_PASSWORD for OTA-Update" +#endif +#ifndef WIFI_PASSWORD +#error "You must define an WIFI_PASSWORD for OTA-Update" +#endif +#ifndef WIFI_SSID +#error "You must define an WIFI_SSID for OTA-Update" +#endif +#ifndef WIFI_AP_PASSWORD +#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode" +#endif + +#endif \ No newline at end of file diff --git a/src/config.cpp b/src/config.cpp new file mode 100644 index 0000000..5abfb5b --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,198 @@ +#include "config.h" + +I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES); +configData_t ConfigData; +persistenceData_t PersistenceData; +uint16_t eePersistenceMarker = 0; +uint16_t eeVersion = 0; // inc +boolean eeAvailable = false; + +const uint16_t startofConfigData = 16; +const uint16_t startofPersistence = 16 + sizeof(startofConfigData) + (sizeof(startofConfigData) % 16); + + +void InitEEPROM() +{ + #ifdef SERIAL_DEBUG + Serial.printf("connecting I2C EEPROM"); + #endif + ee.begin(); + if (!ee.isConnected()) + { + MaintainDTC(DTC_NO_EEPROM_FOUND, true); + } +} + + +void EEPROM_Process() +{ + + switch (globals.requestEEAction) + { + case EE_CFG_SAVE: + StoreConfig_EEPROM(); + globals.requestEEAction = EE_IDLE; + break; + case EE_CFG_LOAD: + GetConfig_EEPROM(); + globals.requestEEAction = EE_IDLE; + break; + case EE_PDS_SAVE: + StorePersistence_EEPROM(); + globals.requestEEAction = EE_IDLE; + break; + case EE_PDS_LOAD: + GetPersistence_EEPROM(); + globals.requestEEAction = EE_IDLE; + break; + case EE_IDLE: + default: + globals.requestEEAction = EE_IDLE; + } +} + +void StoreConfig_EEPROM() +{ + ConfigData.checksum = 0; + ConfigData.checksum = Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)); + + if (!ee.isConnected()) + return; + ee.updateBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData)); +} + +void GetConfig_EEPROM() +{ + + if (!ee.isConnected()) + return; + ee.readBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData)); + + uint32_t checksum = ConfigData.checksum; + ConfigData.checksum = 0; + + if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) != checksum) + { + MaintainDTC(DTC_EEPROM_CFG_BAD, true); + FormatConfig_EEPROM(); + } + ConfigData.checksum = checksum; +} + +uint16_t getPersistanceAddress() +{ + return startofPersistence + eePersistenceMarker; +} + +void StorePersistence_EEPROM() +{ + if (PersistenceData.writeCycleCounter >= 0xFFF0) + MovePersistencePage_EEPROM(false); + else + PersistenceData.writeCycleCounter++; + + PersistenceData.checksum = 0; + PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)); + + if (!ee.isConnected()) + return; + ee.updateBlock(getPersistanceAddress(), (uint8_t *)&PersistenceData, sizeof(PersistenceData)); +} + +void GetPersistence_EEPROM() +{ + + if (!ee.isConnected()) + return; + eePersistenceMarker = (ee.readByte(0) << 8) | ee.readByte(1); + ee.readBlock(getPersistanceAddress(), (uint8_t *)&PersistenceData, sizeof(PersistenceData)); + + uint32_t checksum = PersistenceData.checksum; + PersistenceData.checksum = 0; + + if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum) + { + MaintainDTC(DTC_EEPROM_PDS_BAD, true); + FormatPersistence_EEPROM(); + } + PersistenceData.checksum = checksum; +} + +void FormatConfig_EEPROM() +{ + configData_t defaults; + ConfigData = defaults; + StoreConfig_EEPROM(); +} + +void FormatPersistence_EEPROM() +{ + persistenceData_t defaults; + PersistenceData = defaults; + eePersistenceMarker = 0; + StorePersistence_EEPROM(); +} + +void MovePersistencePage_EEPROM(boolean reset) +{ + eePersistenceMarker = reset ? sizeof(PersistenceData) : eePersistenceMarker + sizeof(PersistenceData); + PersistenceData.writeCycleCounter = 0; + + if (!ee.isConnected()) + return; + ee.updateByte(0, (uint8_t)(eePersistenceMarker >> 8)); + ee.updateByte(1, (uint8_t)(eePersistenceMarker & 0xFF)); +} + +uint32_t Checksum_EEPROM(uint8_t const *data, size_t len) +{ + if (data == NULL) + return 0; + uint32_t crc, mask; + crc = 0xFFFFFFFF; + + while (len--) + { + crc ^= *data++; + for (uint8_t k = 0; k < 8; k++) + { + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +void dumpEEPROM(uint16_t memoryAddress, uint16_t length) +{ +#define BLOCK_TO_LENGTH 16 + + if (!ee.isConnected()) + return; + + char ascii_buf[BLOCK_TO_LENGTH + 1]; + sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII"); + Serial.print(PSTR("\nAddress ")); + for (int x = 0; x < BLOCK_TO_LENGTH; x++) + Serial.printf("%3d", x); + + memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; + length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH; + + for (unsigned int i = 0; i < length; i++) + { + int blockpoint = memoryAddress % BLOCK_TO_LENGTH; + if (blockpoint == 0) + { + ascii_buf[BLOCK_TO_LENGTH] = 0; + Serial.printf(" %s", ascii_buf); + Serial.printf("\n0x%05X:", memoryAddress); + } + ascii_buf[blockpoint] = ee.readByte(memoryAddress); + Serial.printf(" %02X", ascii_buf[blockpoint]); + if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E) + ascii_buf[blockpoint] = '.'; + memoryAddress++; + } + Serial.println(); +} \ No newline at end of file diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..1c4562b --- /dev/null +++ b/src/config.h @@ -0,0 +1,52 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#include +#include +#include + +#include "globals.h" +#include "dtc.h" + +#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256 + +typedef enum +{ + NONE, + FACTION_1, + FACTION_2, + FACTION_3 +} factions_t; + +typedef struct +{ + uint16_t writeCycleCounter = 0; + uint32_t faction_1_timer = 0; + uint32_t faction_2_timer = 0; + uint32_t faction_3_timer = 0; + factions_t activeFaction = NONE; + uint32_t checksum = 0; +} persistenceData_t; + +typedef struct +{ + uint32_t checksum = 0; +} configData_t; + +void InitEEPROM(); +void EEPROM_Process(); +void StoreConfig_EEPROM(); +void GetConfig_EEPROM(); +void StorePersistence_EEPROM(); +void GetPersistence_EEPROM(); +void FormatConfig_EEPROM(); +void FormatPersistence_EEPROM(); +uint32_t Checksum_EEPROM(uint8_t const *data, size_t len); +void dumpEEPROM(uint16_t memoryAddress, uint16_t length); +void MovePersistencePage_EEPROM(boolean reset); +uint16_t getPersistanceAddress(); + +extern configData_t ConfigData; +extern persistenceData_t PersistenceData; +extern uint16_t eePersistenceMarker; +#endif // _CONFIG_H_ \ No newline at end of file diff --git a/src/defaults.h b/src/defaults.h index ebcb522..14ad027 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -2,10 +2,10 @@ #define _DEFAULTS_H_ #ifndef WIFI_CLIENT -#define WIFI_AP +#define WIFI_ACCESSPOINT #endif -#if defined(WIFI_CLIENT) && defined(WIFI_AP) +#if defined(WIFI_CLIENT) && defined(WIFI_ACCESSPOINT) #error "You can't define AP and CLIENT at the same Time!" #endif diff --git a/src/dtc.cpp b/src/dtc.cpp new file mode 100644 index 0000000..f5213ee --- /dev/null +++ b/src/dtc.cpp @@ -0,0 +1,85 @@ +#include "dtc.h" + +DTCEntry_s DTCStorage[MAX_DTC_STORAGE]; + +void MaintainDTC(DTCNums_t DTC_no, boolean active) +{ + for (int i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number == DTC_no) + { + if (active && DTCStorage[i].active != DTC_ACTIVE) + { + Serial.printf("DTC gone active: %d", DTC_no); + DTCStorage[i].timestamp = millis(); + DTCStorage[i].active = DTC_ACTIVE; + } + if (!active && DTCStorage[i].active == DTC_ACTIVE) + { + Serial.printf("DTC gone previous: %d", DTC_no); + DTCStorage[i].active = DTC_PREVIOUS; + } + return; + } + } + + // DTC was not found with upper iteration, but is active + // so we need to look for free space to store DTC + if (active == true) + { + for (int i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number == DTC_LAST_DTC) + { + Serial.printf("new DTC registered: %d", DTC_no); + DTCStorage[i].Number = DTC_no; + DTCStorage[i].timestamp = millis(); + DTCStorage[i].active = DTC_ACTIVE; + return; + } + } + } +} + +void ClearDTC(DTCNums_t DTC_no) +{ + for (int i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number == DTC_no) + { + DTCStorage[i].Number = DTC_LAST_DTC; + DTCStorage[i].active = DTC_NONE; + DTCStorage[i].timestamp = 0; + } + } +} + +void ClearAllDTC() +{ + for (int i = 0; i < MAX_DTC_STORAGE; i++) + { + DTCStorage[i].Number = DTC_LAST_DTC; + DTCStorage[i].active = DTC_NONE; + DTCStorage[i].timestamp = 0; + } +} + +DTCNums_t getlastDTC(boolean only_active) +{ + int8_t pointer = -1; + uint32_t lasttimestamp = 0; + + for (int i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number > 0 && DTCStorage[i].timestamp > lasttimestamp) + { + if (only_active == false || DTCStorage[i].active == DTC_ACTIVE) + { + pointer = i; + lasttimestamp = DTCStorage[i].timestamp; + } + } + } + + return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC; +} \ No newline at end of file diff --git a/src/dtc.h b/src/dtc.h new file mode 100644 index 0000000..d5dc38b --- /dev/null +++ b/src/dtc.h @@ -0,0 +1,36 @@ +#ifndef _DTC_H_ +#define _DTC_H_ + +#include + +#define MAX_DTC_STORAGE 6 + +typedef enum DTCNums_e +{ + DTC_NO_EEPROM_FOUND, + DTC_EEPROM_CFG_BAD, + DTC_EEPROM_PDS_BAD, + DTC_LAST_DTC +} DTCNums_t; + +typedef enum DTCActive_e +{ + DTC_ACTIVE, + DTC_PREVIOUS, + DTC_NONE +} DTCActive_t; + +typedef struct DTCEntry_s +{ + DTCNums_t Number; + uint32_t timestamp; + DTCActive_t active; +} DTCEntry_t; + +void MaintainDTC(DTCNums_t DTC_no, boolean active); +void ClearDTC(DTCNums_t DTC_no); +void ClearAllDTC(); +DTCNums_t getlastDTC(boolean only_active); + +extern DTCEntry_s DTCStorage[MAX_DTC_STORAGE]; +#endif \ No newline at end of file diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..42f47a4 --- /dev/null +++ b/src/globals.h @@ -0,0 +1,36 @@ +#ifndef _GLOBALS_H_ +#define _GLOBALS_H_ + +#include + +typedef enum eSystem_Status +{ + sysStat_Startup, + sysStat_Normal, + sysStat_Error, + sysStat_Shutdown +} tSystem_Status; + +typedef enum eEERequest +{ + EE_IDLE, + EE_CFG_SAVE, + EE_CFG_LOAD, + EE_PDS_SAVE, + EE_PDS_LOAD +} tEERequest; + +typedef struct Globals_s +{ + char DeviceName[33]; + char DeviceName_ID[33+6]; + tSystem_Status systemStatus = sysStat_Startup; + tSystem_Status resumeStatus = sysStat_Startup; + eEERequest requestEEAction = EE_IDLE; + float loadvoltage = 0; + int battery_level = 0; +} Globals_t; + +extern Globals_t globals; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index a267dd8..97d124f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,50 +1,68 @@ #include #include #include -#ifdef CAPTIVE #include -#endif -#ifdef ESP32 -#include -#include -#include -#elif defined(ESP8266) #include #include -#include #include -#endif #include #include #include #include #include + // local includes #include "defaults.h" +#include "webui.h" +#include "config.h" +#include "globals.h" +#include "dtc.h" +#include "common.h" -// Module connection pins (ESP GPIO-Nums) -#define CLK 16 -#define DIO_FAC_1_7SEG 14 -#define DIO_FAC_2_7SEG 12 -#define DIO_FAC_3_7SEG 13 +#ifdef REMOTE_DEBUG +#include +#include "rmtdbghelp.h" +#else +#define debugV Serial.println +#define debugE Serial.println +#endif -#define DIO_FAC_1_TRG 0 -#define DIO_FAC_2_TRG 2 -#define DIO_FAC_3_TRG 15 +#ifdef WIFI_CLIENT +#include -enum Factions -{ - NONE, - FACTION_1, - FACTION_2, - FACTION_3 -}; +const char *ssid = QUOTE(WIFI_SSID); +const char *password = QUOTE(WIFI_PASSWORD); +const uint32_t connectTimeoutMs = 5000; + +ESP8266WiFiMulti wifiMulti; +#endif void SevenSeg_Output(); void FactionTicker_callback(); -void serialOutTicker_callback(); void inputGetterTicker_callback(); void powerMonitorTicker_callback(); +void EEPROMCyclicPDS_callback(); +void toggleWiFiAP(boolean shutdown = false); +void SystemShutdown(); + +#ifdef REMOTE_DEBUG +RemoteDebug Debug; +String IpAddress2String(const IPAddress &ipAddress); +void processCmdRemoteDebug(); +void RemoteDebug_formatCFG(); +void RemoteDebug_formatPersistence(); +void RemotDebug_printSystemInfo(); +void RemoteDebug_printWifiInfo(); +void RemoteDebug_CheckEEPOM(); +void RemoteDebug_dumpConfig(); +void RemoteDebug_dumpPersistance(); +void RemoteDebug_ShowDTCs(); +#endif + +#ifdef WIFI_CLIENT +void wifiMaintainConnectionTicker_callback(); +Ticker WiFiMaintainConnectionTicker(wifiMaintainConnectionTicker_callback, 1000, 0, MILLIS); +#endif TM1637Display disp_FAC_1(CLK, DIO_FAC_1_7SEG); TM1637Display disp_FAC_2(CLK, DIO_FAC_2_7SEG); @@ -52,309 +70,56 @@ TM1637Display disp_FAC_3(CLK, DIO_FAC_3_7SEG); Adafruit_INA219 ina219; -WiFiEventHandler stationConnectedHandler; -WiFiEventHandler stationDisconnectedHandler; - -#ifdef WIFI_CLIENT -ESP8266WiFiMulti wifiMulti; -#endif - #ifdef CAPTIVE DNSServer dnsServer; #endif AsyncWebServer server(80); Ticker FactionTicker(FactionTicker_callback, 1000, 0, MILLIS); -Ticker SerialOutputTicker(serialOutTicker_callback, 5000, 0, MILLIS); Ticker InputGetterTicker(inputGetterTicker_callback, 250, 0, MILLIS); Ticker PowerMonitorTicker(powerMonitorTicker_callback, 5000, 0, MILLIS); +Ticker EEPROMCyclicPDSTicker(EEPROMCyclicPDS_callback, 60000, 0, MILLIS); -Factions activeFaction = NONE; - -uint32_t Count_Faction_1 = 0; -uint32_t Count_Faction_2 = 0; -uint32_t Count_Faction_3 = 0; uint8_t Faction_1_dot = 0; uint8_t Faction_2_dot = 0; uint8_t Faction_3_dot = 0; -float loadvoltage = 0; -int battery_level = 0; +Globals_t globals; const uint8_t sevenSeg_bat[] = {0x00, 0b01111100, 0b01110111, 0b01111000}; const uint8_t sevenSeg_low[] = {0b00111000, 0b01011100, 0x00, 0x00}; -String processor(const String &var) -{ - char buffer[16] = {0}; - - if (var == "POINTS_FAC_1") - itoa(Count_Faction_1, buffer, 10); - - if (var == "POINTS_FAC_2") - itoa(Count_Faction_2, buffer, 10); - - if (var == "POINTS_FAC_3") - itoa(Count_Faction_3, buffer, 10); - - if (var == "STATUS_FAC_1") - return activeFaction == FACTION_1 ? "ACTIVE" : "INACTIVE"; - - if (var == "STATUS_FAC_2") - return activeFaction == FACTION_2 ? "ACTIVE" : "INACTIVE"; - - if (var == "STATUS_FAC_3") - return activeFaction == FACTION_3 ? "ACTIVE" : "INACTIVE"; - - if (var == "NAME_FAC_1") - return FACTION_1_NAME; - - if (var == "NAME_FAC_2") - return FACTION_2_NAME; - - if (var == "NAME_FAC_3") - return FACTION_3_NAME; - - if (var == "TITLE") - return DEVICE_NAME; - - if (var == "BATTERY_LEVEL") - { - sprintf(buffer, "%d", battery_level); - return String(buffer); - } - if (var == "BATTERY_VOLTAGE") - { - sprintf(buffer, "%f", loadvoltage); - return String(buffer); - } - return String(buffer); -} - -String macToString(const unsigned char *mac) -{ - char buf[20]; - snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return String(buf); -} - -void onStationConnected(const WiFiEventSoftAPModeStationConnected &evt) -{ - Serial.print("Station connected: "); - Serial.println(macToString(evt.mac)); -} - -void onStationDisconnected(const WiFiEventSoftAPModeStationDisconnected &evt) -{ - Serial.print("Station disconnected: "); - Serial.println(macToString(evt.mac)); -} - -String getValue(String data, char separator, int index) -{ - int found = 0; - int strIndex[] = {0, -1}; - int maxIndex = data.length() - 1; - - for (int i = 0; i <= maxIndex && found <= index; i++) - { - if (data.charAt(i) == separator || i == maxIndex) - { - found++; - strIndex[0] = strIndex[1] + 1; - strIndex[1] = (i == maxIndex) ? i + 1 : i; - } - } - - return found > index ? data.substring(strIndex[0], strIndex[1]) : ""; -} - -class CaptiveRequestHandler : public AsyncWebHandler -{ -public: - CaptiveRequestHandler() {} - virtual ~CaptiveRequestHandler() {} - - bool canHandle(AsyncWebServerRequest *request) - { - return true; - } - - void handleRequest(AsyncWebServerRequest *request) - { - - Serial.print("Requested URL: "); - Serial.println(request->url()); - - //List all parameters - int params = request->params(); - for (int i = 0; i < params; i++) - { - AsyncWebParameter *p = request->getParam(i); - if (p->isFile()) - { //p->isPost() is also true - Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); - } - else if (p->isPost()) - { - Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } - else - { - Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); - } - } - - if (LittleFS.exists(request->url()) == false) - { - request->send(404, "text/plain", "Not found"); - return; - } - - if (request->url() == "/favicon.ico") - { - request->send(LittleFS, request->url(), "image/x-icon"); - return; - } - - if (request->url() == "/" || request->url() == "/index.html") - { - request->send(LittleFS, "/index.html", String(), false, processor); - return; - } - - if (getValue(request->url(), '/', 1) == "css") - { - request->send(LittleFS, request->url(), "text/css"); - return; - } - } -}; - -void SevenSeg_Output() -{ - if (battery_level < BAT_LOW_PERCENT) - { - disp_FAC_1.setBrightness(0); - disp_FAC_2.setBrightness(0); - disp_FAC_3.setBrightness(0); - - disp_FAC_3.setSegments(sevenSeg_bat); - disp_FAC_2.setSegments(sevenSeg_low); - if (millis() % 5000 > 2500) - disp_FAC_1.showNumberDec(battery_level); - else - disp_FAC_1.showNumberDecEx(loadvoltage * 100, 0x40); - } - else - { - disp_FAC_1.setBrightness(activeFaction == FACTION_1 ? 7 : 0); - disp_FAC_2.setBrightness(activeFaction == FACTION_2 ? 7 : 0); - disp_FAC_3.setBrightness(activeFaction == FACTION_3 ? 7 : 0); - - disp_FAC_1.showNumberDecEx(Count_Faction_1 / 60, Faction_1_dot, true, 4, 0); - disp_FAC_2.showNumberDecEx(Count_Faction_2 / 60, Faction_2_dot, true, 4, 0); - disp_FAC_3.showNumberDecEx(Count_Faction_3 / 60, Faction_3_dot, true, 4, 0); - } -} - -void FactionTicker_callback() -{ - switch (activeFaction) - { - case FACTION_1: - Count_Faction_1++; - Faction_1_dot = Faction_1_dot == 0x80 || Faction_1_dot == 0x00 ? 0x10 : Faction_1_dot << 1; - Faction_2_dot = 0; - Faction_3_dot = 0; - break; - - case FACTION_2: - Count_Faction_2++; - Faction_2_dot = Faction_2_dot == 0x80 || Faction_2_dot == 0x00 ? 0x10 : Faction_2_dot << 1; - Faction_1_dot = 0; - Faction_3_dot = 0; - break; - - case FACTION_3: - Count_Faction_3++; - Faction_3_dot = Faction_3_dot == 0x80 || Faction_3_dot == 0x00 ? 0x10 : Faction_3_dot << 1; - Faction_1_dot = 0; - Faction_2_dot = 0; - break; - - default: - break; - } -} - -void serialOutTicker_callback() -{ - - static uint32_t SerialPrintCount = 0; - - if (SerialPrintCount % 10 == 0) - { - Serial.printf("| %8s | %8s | %8s |\n", FACTION_1_NAME, FACTION_2_NAME, FACTION_3_NAME); - } - Serial.printf(" %8d %8d %8d\n", Count_Faction_1, Count_Faction_2, Count_Faction_3); - SerialPrintCount++; -} - -void inputGetterTicker_callback() -{ - activeFaction = NONE; - - if (digitalRead(DIO_FAC_1_TRG) + digitalRead(DIO_FAC_2_TRG) + !digitalRead(DIO_FAC_3_TRG) < 2) - { - Serial.println("ERROR: More than one Flag active"); - return; - } - - if (digitalRead(DIO_FAC_1_TRG) == LOW) - activeFaction = FACTION_1; - - if (digitalRead(DIO_FAC_2_TRG) == LOW) - activeFaction = FACTION_2; - - if (digitalRead(DIO_FAC_3_TRG) == HIGH) - activeFaction = FACTION_3; -} - -void powerMonitorTicker_callback() -{ - - // loadvoltage and percentage is global, because of battery Monitoring - - float shuntvoltage = 0; - float current_mA = 0; - float busvoltage = 0; - float power_mW = 0; - - shuntvoltage = ina219.getShuntVoltage_mV(); - busvoltage = ina219.getBusVoltage_V(); - current_mA = ina219.getCurrent_mA(); - power_mW = ina219.getPower_mW(); - loadvoltage = busvoltage + (shuntvoltage / 1000); - battery_level = map(loadvoltage * 100, 655, 840, 0, 100); - - Serial.printf("Battery Level: %d %%\n", battery_level); - Serial.printf("Bus Voltage: %f V\n", busvoltage); - Serial.printf("Shunt Voltage: %f mV\n", shuntvoltage); - Serial.printf("Load Voltage: %f V\n", loadvoltage); - Serial.printf("Current: %f mA\n", current_mA); - Serial.printf("Power: %f mW\n", power_mW); -} - void setup() { + system_update_cpu_freq(SYS_CPU_80MHZ); + WiFi.persistent(false); + + Serial.begin(115200); + Serial.print("\n\n\n"); + + strcpy(globals.DeviceName, DEVICE_NAME); + snprintf(globals.DeviceName_ID, 39, "%s_%06X", globals.DeviceName, ESP.getChipId()); + pinMode(DIO_FAC_1_TRG, INPUT_PULLUP); pinMode(DIO_FAC_2_TRG, INPUT_PULLUP); pinMode(DIO_FAC_3_TRG, INPUT); - Serial.begin(9600); - Serial.print("\n\n\n"); +#ifdef REMOTE_DEBUG + if (MDNS.begin(globals.DeviceName_ID)) + MDNS.addService("telnet", "tcp", 23); + + Debug.begin(globals.DeviceName_ID); + Debug.setResetCmdEnabled(true); + Debug.showProfiler(false); + Debug.showColors(true); + Debug.setPassword(QUOTE(ADMIN_PASSWORD)); + Debug.setSerialEnabled(true); + Debug.showDebugLevel(true); + + Debug.setHelpProjectsCmds(helpCmd); + Debug.setCallBackProjectCmds(&processCmdRemoteDebug); +#endif + #ifdef SERIAL_DEBUG Serial.setDebugOutput(true); #endif @@ -366,32 +131,22 @@ void setup() LittleFS.begin(); - WiFi.persistent(false); - -#ifdef WIFI_AP - WiFi.mode(WIFI_AP); - WiFi.softAP(WIFI_SSID, WIFI_PASS); - - stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected); - stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onStationDisconnected); - -#else +#ifdef WIFI_CLIENT WiFi.mode(WIFI_STA); - wifiMulti.addAP(WIFI_SSID, WIFI_PASS); - - Serial.println("Connecting Wifi..."); - if (wifiMulti.run() == WL_CONNECTED) - { - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.print(WiFi.localIP()); - } + WiFi.setHostname(globals.DeviceName_ID); + wifiMulti.addAP(QUOTE(WIFI_SSID), QUOTE(WIFI_PASSWORD)); + WiFiMaintainConnectionTicker.start(); +#else + WiFi.mode(WIFI_OFF); #endif + InitEEPROM(); + GetConfig_EEPROM(); + GetPersistence_EEPROM(); + ArduinoOTA.setPort(8266); - ArduinoOTA.setHostname(OTA_HOST); - ArduinoOTA.setPassword(OTA_PASS); + ArduinoOTA.setHostname(globals.DeviceName_ID); + ArduinoOTA.setPassword(QUOTE(ADMIN_PASSWORD)); ArduinoOTA.onStart([]() { @@ -405,8 +160,7 @@ void setup() type = "filesystem"; LittleFS.end(); } - Serial.println("Start updating " + type); - }); + Serial.println("Start updating " + type); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); @@ -426,70 +180,346 @@ void setup() else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) - Serial.println("End Failed"); - }); + Serial.println("End Failed"); }); ArduinoOTA.begin(); #ifdef CAPTIVE dnsServer.start(53, "*", WiFi.softAPIP()); #endif - server.addHandler(new CaptiveRequestHandler()); - server.begin(); + initWebUI(); + EEPROMCyclicPDSTicker.start(); FactionTicker.start(); - SerialOutputTicker.start(); InputGetterTicker.start(); + Serial.println("Setup Done"); } void loop() { + EEPROMCyclicPDSTicker.update(); FactionTicker.update(); - SerialOutputTicker.update(); InputGetterTicker.update(); PowerMonitorTicker.update(); ArduinoOTA.handle(); + SevenSeg_Output(); + EEPROM_Process(); #ifdef CAPTIVE dnsServer.processNextRequest(); #endif +#ifdef REMOTE_DEBUG + Debug.handle(); +#endif +#ifdef WIFI_CLIENT + WiFiMaintainConnectionTicker.update(); +#endif + if (globals.systemStatus == sysStat_Shutdown) + SystemShutdown(); + yield(); +} - SevenSeg_Output(); +String macToString(const unsigned char *mac) +{ + char buf[20]; + snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return String(buf); +} - while (Serial.available() > 0) +void SevenSeg_Output() +{ + if (globals.battery_level < BAT_LOW_PERCENT) { - char input = Serial.read(); + disp_FAC_1.setBrightness(0); + disp_FAC_2.setBrightness(0); + disp_FAC_3.setBrightness(0); - switch (input) + disp_FAC_3.setSegments(sevenSeg_bat); + disp_FAC_2.setSegments(sevenSeg_low); + if (millis() % 5000 > 2500) + disp_FAC_1.showNumberDec(globals.battery_level); + else + disp_FAC_1.showNumberDecEx(globals.loadvoltage * 100, 0x40); + } + else + { + disp_FAC_1.setBrightness(PersistenceData.activeFaction == FACTION_1 ? 7 : 0); + disp_FAC_2.setBrightness(PersistenceData.activeFaction == FACTION_2 ? 7 : 0); + disp_FAC_3.setBrightness(PersistenceData.activeFaction == FACTION_3 ? 7 : 0); + + disp_FAC_1.showNumberDecEx(PersistenceData.faction_1_timer / 60, Faction_1_dot, true, 4, 0); + disp_FAC_2.showNumberDecEx(PersistenceData.faction_2_timer / 60, Faction_2_dot, true, 4, 0); + disp_FAC_3.showNumberDecEx(PersistenceData.faction_3_timer / 60, Faction_3_dot, true, 4, 0); + } +} + +void FactionTicker_callback() +{ + switch (PersistenceData.activeFaction) + { + case FACTION_1: + PersistenceData.faction_1_timer++; + Faction_1_dot = Faction_1_dot == 0x80 || Faction_1_dot == 0x00 ? 0x10 : Faction_1_dot << 1; + Faction_2_dot = 0; + Faction_3_dot = 0; + break; + + case FACTION_2: + PersistenceData.faction_2_timer++; + Faction_2_dot = Faction_2_dot == 0x80 || Faction_2_dot == 0x00 ? 0x10 : Faction_2_dot << 1; + Faction_1_dot = 0; + Faction_3_dot = 0; + break; + + case FACTION_3: + PersistenceData.faction_3_timer++; + Faction_3_dot = Faction_3_dot == 0x80 || Faction_3_dot == 0x00 ? 0x10 : Faction_3_dot << 1; + Faction_1_dot = 0; + Faction_2_dot = 0; + break; + + default: + break; + } +} + +void inputGetterTicker_callback() +{ + + if (digitalRead(DIO_FAC_1_TRG) + digitalRead(DIO_FAC_2_TRG) + !digitalRead(DIO_FAC_3_TRG) < 2) + { + Serial.println("ERROR: More than one Flag active - setting no Faction active"); + PersistenceData.activeFaction = NONE; + return; + } + + if (digitalRead(DIO_FAC_1_TRG) == LOW) + PersistenceData.activeFaction = FACTION_1; + + if (digitalRead(DIO_FAC_2_TRG) == LOW) + PersistenceData.activeFaction = FACTION_2; + + if (digitalRead(DIO_FAC_3_TRG) == HIGH) + PersistenceData.activeFaction = FACTION_3; +} + +void powerMonitorTicker_callback() +{ + + // loadvoltage and percentage is global, because of battery Monitoring + + float shuntvoltage = 0; + float current_mA = 0; + float busvoltage = 0; + float power_mW = 0; + + shuntvoltage = ina219.getShuntVoltage_mV(); + busvoltage = ina219.getBusVoltage_V(); + current_mA = ina219.getCurrent_mA(); + power_mW = ina219.getPower_mW(); + globals.loadvoltage = busvoltage + (shuntvoltage / 1000); + globals.battery_level = map(globals.loadvoltage * 100, 655, 840, 0, 100); + + debugV("Battery Level: %d %%", globals.battery_level); + debugV("Bus Voltage: %f V", busvoltage); + debugV("Shunt Voltage: %f mV", shuntvoltage); + debugV("Load Voltage: %f V", globals.loadvoltage); + debugV("Current: %f mA", current_mA); + debugV("Power: %f mW", power_mW); +} + +void EEPROMCyclicPDS_callback() +{ + StorePersistence_EEPROM(); +} + +#ifdef WIFI_CLIENT +void wifiMaintainConnectionTicker_callback() +{ + static uint32_t WiFiFailCount = 0; + const uint32_t WiFiFailMax = 20; + + if (wifiMulti.run(connectTimeoutMs) == WL_CONNECTED) + { + return; + } + else + { + if (WiFiFailCount < WiFiFailMax) + WiFiFailCount++; + else + toggleWiFiAP(false); + } +} +#endif + +void toggleWiFiAP(boolean shutdown) +{ + if (WiFi.getMode() != WIFI_OFF && shutdown == true) + { + WiFi.mode(WIFI_OFF); +#ifdef WIFI_CLIENT + WiFiMaintainConnectionTicker.stop(); +#endif + } + else if (shutdown == false) + { + WiFi.mode(WIFI_AP); + WiFi.softAPConfig(IPAddress(WIFI_AP_IP_GW), IPAddress(WIFI_AP_IP_GW), IPAddress(255, 255, 255, 0)); + WiFi.softAP(globals.DeviceName_ID, QUOTE(WIFI_AP_PASSWORD)); +#ifdef WIFI_CLIENT + WiFiMaintainConnectionTicker.stop(); +#endif + } +} + +void SystemShutdown() +{ + StoreConfig_EEPROM(); + ESP.restart(); +} + +#ifdef REMOTE_DEBUG +void processCmdRemoteDebug() +{ + String lastCmd = Debug.getLastCommand(); + + if (lastCmd == "sysinfo") + RemotDebug_printSystemInfo(); + else if (lastCmd == "netinfo") + RemoteDebug_printWifiInfo(); + else if (lastCmd == "formatCFG") + RemoteDebug_formatCFG(); + else if (lastCmd == "formatPDS") + RemoteDebug_formatPersistence(); + else if (lastCmd == "checkEE") + RemoteDebug_CheckEEPOM(); + else if (lastCmd == "dumpEE1k") + dumpEEPROM(0, 1024); + else if (lastCmd == "dumpEE") + dumpEEPROM(0, EEPROM_SIZE_BYTES); + else if (lastCmd == "resetPageEE") + MovePersistencePage_EEPROM(true); + else if (lastCmd == "dumpCFG") + RemoteDebug_dumpConfig(); + else if (lastCmd == "dumpPDS") + RemoteDebug_dumpPersistance(); + else if (lastCmd == "saveEE") + StoreConfig_EEPROM(); + else if (lastCmd == "showdtc") + RemoteDebug_ShowDTCs(); +} + +void RemoteDebug_formatCFG() +{ + debugA("Formatting Config-EEPROM and reseting to default"); + FormatConfig_EEPROM(); +} + +void RemoteDebug_formatPersistence() +{ + debugA("Formatting Persistence-EEPROM and reseting to default"); + FormatPersistence_EEPROM(); +} + +void RemotDebug_printSystemInfo() +{ + debugA("DE Timer Mk1"); + debugA("Hostname: %s", globals.DeviceName_ID); + + FlashMode_t ideMode = ESP.getFlashChipMode(); + debugA("Sdk version: %s", ESP.getSdkVersion()); + debugA("Core Version: %s", ESP.getCoreVersion().c_str()); + debugA("Boot Version: %u", ESP.getBootVersion()); + debugA("Boot Mode: %u", ESP.getBootMode()); + debugA("CPU Frequency: %u MHz", ESP.getCpuFreqMHz()); + debugA("Reset reason: %s", ESP.getResetReason().c_str()); + debugA("Flash Size: %d", ESP.getFlashChipRealSize()); + debugA("Flash Size IDE: %d", ESP.getFlashChipSize()); + debugA("Flash ide mode: %s", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT" + : ideMode == FM_DIO ? "DIO" + : ideMode == FM_DOUT ? "DOUT" + : "UNKNOWN")); + debugA("OTA-Pass: %s", QUOTE(ADMIN_PASSWORD)); + debugA("Git-Revison: %s", GIT_REV); +} + +void RemoteDebug_dumpConfig() +{ + debugA("checksum: 0x%08X", ConfigData.checksum); +} + +void RemoteDebug_dumpPersistance() +{ + debugA("writeCycleCounter: %d", PersistenceData.writeCycleCounter); + debugA("faction_1_timer: %d", PersistenceData.faction_1_timer); + debugA("faction_2_timer: %d", PersistenceData.faction_2_timer); + debugA("faction_2_timer: %d", PersistenceData.faction_3_timer); + debugA("activeFaction: %d", PersistenceData.activeFaction); + debugA("checksum: %d", PersistenceData.checksum); + debugA("PSD Adress: 0x%04X", getPersistanceAddress()); +} + +void RemoteDebug_printWifiInfo() +{ +} + +void RemoteDebug_CheckEEPOM() +{ + uint32_t checksum = PersistenceData.checksum; + PersistenceData.checksum = 0; + + if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) == checksum) + { + debugA("PersistenceData EEPROM Checksum OK\n"); + } + else + { + debugA("PersistenceData EEPROM Checksum BAD\n"); + } + + PersistenceData.checksum = checksum; + + checksum = ConfigData.checksum; + ConfigData.checksum = 0; + + if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) == checksum) + { + debugA("ConfigData EEPROM Checksum OK\n"); + } + else + { + debugA("ConfigData EEPROM Checksum BAD\n"); + } + ConfigData.checksum = checksum; +} + +void RemoteDebug_ShowDTCs() +{ + char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx + char buff_active[9]; + + for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number > 0) { - case 'n': - activeFaction = NONE; - break; + sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", + DTCStorage[i].timestamp / 86400000, // Days + DTCStorage[i].timestamp / 360000 % 24, // Hours + DTCStorage[i].timestamp / 60000 % 60, // Minutes + DTCStorage[i].timestamp / 1000 % 60, // Seconds + DTCStorage[i].timestamp % 1000); // milliseconds - case 'g': - activeFaction = FACTION_1; - break; + if (DTCStorage[i].active == DTC_ACTIVE) + strcpy(buff_active, "active"); + else if (DTCStorage[i].active == DTC_PREVIOUS) + strcpy(buff_active, "previous"); + else + strcpy(buff_active, "none"); - case 'k': - activeFaction = FACTION_3; - break; - - case 'm': - activeFaction = FACTION_2; - break; - - case 'x': - SerialOutputTicker.stop(); - Serial.println("SerialOutputTicker.stop()"); - break; - - case 'y': - SerialOutputTicker.resume(); - Serial.println("SerialOutputTicker.resume()"); - break; - - default: - break; + debugA("%s \t %6d \t %s", buff_timestamp, DTCStorage[i].Number, buff_active); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/rmtdbghelp.h b/src/rmtdbghelp.h new file mode 100644 index 0000000..dbede2b --- /dev/null +++ b/src/rmtdbghelp.h @@ -0,0 +1,13 @@ +const char helpCmd[] = "sysinfo - System Info\r\n" + "netinfo - WiFi Info\r\n" + "showdtc - Show all DTCs\r\n" + "cleardtc - Clear all DTCs\r\n" + "formatPDS - Format Persistence EEPROM Data\r\n" + "formatCFG - Format Configuration EEPROM Data\r\n" + "checkEE - Check EEPROM with checksum\r\n" + "dumpEE1k - dump the first 1kb of EEPROM to Serial\r\n" + "dumpEE - dump the whole EPPROM to Serial\r\n" + "resetPageEE - Reset the PersistenceData Page\r\n" + "dumpCFG - print Config struct\r\n" + "dumpPDS - print PersistanceStruct\r\n" + "saveEE - save EE-Data\r\n"; \ No newline at end of file diff --git a/src/webui.cpp b/src/webui.cpp new file mode 100644 index 0000000..86850ae --- /dev/null +++ b/src/webui.cpp @@ -0,0 +1,162 @@ +#include "webui.h" + +AsyncWebServer webServer(80); + +const char *PARAM_MESSAGE = "message"; + +String processor(const String &var); +void WebserverPOST_Callback(AsyncWebServerRequest *request); +void WebserverNotFound_Callback(AsyncWebServerRequest *request); +void Webserver_Callback(AsyncWebServerRequest *request); + +void initWebUI() +{ + if (!LittleFS.begin()) + { + Serial.println("An Error has occurred while mounting LittleFS"); + return; + } + + webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000"); + webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) + { request->redirect("/index.htm"); }); + webServer.onNotFound(WebserverNotFound_Callback); + webServer.on("/index.htm", HTTP_GET, Webserver_Callback); + webServer.on("/post.htm", HTTP_POST, WebserverPOST_Callback); + + webServer.begin(); +} + +String processor(const String &var) +{ + if (var == "SHOW_DTC_TABLE") + return globals.systemStatus == sysStat_Error ? "" : "hidden"; + + if (var == "BAT_REMAIN_CAPACITY") + return String(globals.battery_level); + + if (var == "DEVICE_NAME") + return String(globals.DeviceName); + + if (var == "BAT_VOLTAGE") + return String(globals.loadvoltage); + + if (var == "DTC_TABLE") + { + String temp; + char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx + + for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) + { + if (DTCStorage[i].Number > 0) + { + sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", + DTCStorage[i].timestamp / 86400000, // Days + DTCStorage[i].timestamp / 360000 % 24, // Hours + DTCStorage[i].timestamp / 60000 % 60, // Minutes + DTCStorage[i].timestamp / 1000 % 60, // Seconds + DTCStorage[i].timestamp % 1000); // milliseconds + + temp = "" + String(buff_timestamp); + temp = temp + "" + String(DTCStorage[i].Number) + ""; + + if (DTCStorage[i].active == DTC_ACTIVE) + temp = temp + "active"; + else if (DTCStorage[i].active == DTC_PREVIOUS) + temp = temp + "previous"; + else + temp = temp + "none"; + + temp = temp + ""; + } + } + return temp; + } + + if (var == "PLACEHOLDER") + return "placeholder"; + + if (var == "POINTS_FAC_1") + { + char buff[12]; + snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_1_timer / 3600, (PersistenceData.faction_1_timer / 60) % 60, PersistenceData.faction_1_timer % 60); + return String(buff); + } + + if (var == "POINTS_FAC_2") + { + char buff[12]; + snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_2_timer / 3600, (PersistenceData.faction_2_timer / 60) % 60, PersistenceData.faction_2_timer % 60); + return String(buff); + } + + if (var == "POINTS_FAC_3") + { + char buff[12]; + snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_3_timer / 3600, (PersistenceData.faction_3_timer / 60) % 60, PersistenceData.faction_3_timer % 60); + return String(buff); + } + + if (var == "STATUS_FAC_1") + return PersistenceData.activeFaction == FACTION_1 ? "ACTIVE" : "INACTIVE"; + + if (var == "STATUS_FAC_2") + return PersistenceData.activeFaction == FACTION_2 ? "ACTIVE" : "INACTIVE"; + + if (var == "STATUS_FAC_3") + return PersistenceData.activeFaction == FACTION_3 ? "ACTIVE" : "INACTIVE"; + + if (var == "NAME_FAC_1") + return FACTION_1_NAME; + + if (var == "NAME_FAC_2") + return FACTION_2_NAME; + + if (var == "NAME_FAC_3") + return FACTION_3_NAME; + + if (var == "TITLE") + return DEVICE_NAME; + + if (var == "BATTERY_LEVEL") + { + return String(globals.battery_level); + } + if (var == "BATTERY_VOLTAGE") + { + return String(globals.loadvoltage); + } + + return String(); +} + +void Webserver_Callback(AsyncWebServerRequest *request) +{ + request->send(LittleFS, "/index.htm", "text/html", false, processor); +} + +void WebserverPOST_Callback(AsyncWebServerRequest *request) +{ + request->send(LittleFS, "/post.htm", "text/html", false, processor); + + Serial.print("POST:\n"); + int paramsNr = request->params(); + for (int i = 0; i < paramsNr; i++) + { + AsyncWebParameter *p = request->getParam(i); + Serial.printf("%s : %s\n", p->name().c_str(), p->value().c_str()); + + if (p->name() == "resetcount") + { + PersistenceData.faction_1_timer = 0; + PersistenceData.faction_2_timer = 0; + PersistenceData.faction_3_timer = 0; + globals.requestEEAction = EE_PDS_SAVE; + } + } +} + +void WebserverNotFound_Callback(AsyncWebServerRequest *request) +{ + request->send(404, "text/html", "Not found"); +} \ No newline at end of file diff --git a/src/webui.h b/src/webui.h new file mode 100644 index 0000000..af82387 --- /dev/null +++ b/src/webui.h @@ -0,0 +1,15 @@ +#ifndef _WEBUI_H_ +#define _WEBUI_H_ + +#include +#include +#include +#include +#include +#include "config.h" +#include "globals.h" +#include "dtc.h" + +void initWebUI(); + +#endif \ No newline at end of file diff --git a/wifi_credentials.example.ini b/wifi_credentials.example.ini new file mode 100644 index 0000000..51d0d6d --- /dev/null +++ b/wifi_credentials.example.ini @@ -0,0 +1,5 @@ +[wifi_cred] +wifi_ap_password = wifiappass +wifi_ssid = wifi-ssid +wifi_password = wifi-pass +admin_password = ota-password \ No newline at end of file