diff --git a/Software/USER_SETTINGS.cpp b/Software/USER_SETTINGS.cpp index 9ef1f9d5..bcc2a677 100644 --- a/Software/USER_SETTINGS.cpp +++ b/Software/USER_SETTINGS.cpp @@ -16,11 +16,6 @@ volatile uint16_t MAXDISCHARGEAMP = 300; //30.0A , BYD CAN specific setting, Max discharge speed in Amp (Some inverters needs to be artificially limited) /* Charger settings (Optional, when generator charging) */ -// MQTT -#ifdef MQTT -const char* mqtt_user = "REDACTED"; -const char* mqtt_password = "REDACTED"; -#endif // USE_MQTT /* Charger settings */ volatile float CHARGER_SET_HV = 384; // Reasonably appropriate 4.0v per cell charging of a 96s pack volatile float CHARGER_MAX_HV = 420; // Max permissible output (VDC) of charger @@ -37,4 +32,11 @@ const char* password = "REPLACE_WITH_YOUR_PASSWORD"; // Minimum of 8 characters const char* ssidAP = "Battery Emulator"; // Maximum of 63 characters; const char* passwordAP = "123456789"; // Minimum of 8 characters; set to NULL if you want the access point to be open const uint8_t wifi_channel = 0; // set to 0 for automatic channel selection + +// MQTT +#ifdef MQTT +const char* mqtt_user = "REDACTED"; +const char* mqtt_password = "REDACTED"; +#endif // USE_MQTT + #endif diff --git a/Software/USER_SETTINGS.h b/Software/USER_SETTINGS.h index 4b69ef06..4ba402a6 100644 --- a/Software/USER_SETTINGS.h +++ b/Software/USER_SETTINGS.h @@ -37,7 +37,7 @@ //#define SERIAL_LINK_RECEIVER //Enable this line to receive battery data over RS485 pins from another Lilygo (This LilyGo interfaces with inverter) //#define SERIAL_LINK_TRANSMITTER //Enable this line to send battery data over RS485 pins to another Lilygo (This LilyGo interfaces with battery) #define WEBSERVER //Enable this line to enable WiFi, and to run the webserver. See USER_SETTINGS.cpp for the Wifi settings. -//#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot +#define LOAD_SAVED_SETTINGS_ON_BOOT //Enable this line to read settings stored via the webserver on boot /* MQTT options */ //#define MQTT // Enable this line to enable MQTT @@ -47,7 +47,6 @@ #define MQTT_PORT 1883 /* Event options*/ -#define EVENTLOGGING //Enable this line to log events to the event log #define DUMMY_EVENT_ENABLED false //Enable this line to have a dummy event that gets logged to test the interface /* Select charger used (Optional) */ diff --git a/Software/src/devboard/webserver/cellmonitor_html.cpp b/Software/src/devboard/webserver/cellmonitor_html.cpp new file mode 100644 index 00000000..1051e87c --- /dev/null +++ b/Software/src/devboard/webserver/cellmonitor_html.cpp @@ -0,0 +1,56 @@ +#include "cellmonitor_html.h" +#include + +String cellmonitor_processor(const String& var) { + if (var == "PLACEHOLDER") { + String content = ""; + // Page format + content += ""; + + // Start a new block with a specific background color + content += "
"; + + // Display max, min, and deviation voltage values + content += "
"; + content += "Max Voltage: " + String(cell_max_voltage) + " mV
"; + content += "Min Voltage: " + String(cell_min_voltage) + " mV
"; + int deviation = cell_max_voltage - cell_min_voltage; + content += "Voltage Deviation: " + String(deviation) + " mV"; + content += "
"; + + // Visualize the populated cells in forward order using flexbox with conditional text color + content += "
"; + for (int i = 0; i < 120; ++i) { + // Skip empty values + if (cellvoltages[i] == 0) { + continue; + } + + String cellContent = "Cell " + String(i + 1) + "
" + String(cellvoltages[i]) + " mV"; + + // Check if the cell voltage is below 3000, apply red color + if (cellvoltages[i] < 3000) { + cellContent = "" + cellContent + ""; + } + + content += "
" + cellContent + "
"; + } + content += "
"; + + // Close the block + content += "
"; + + content += ""; + content += ""; + return content; + } + return String(); +} diff --git a/Software/src/devboard/webserver/cellmonitor_html.h b/Software/src/devboard/webserver/cellmonitor_html.h new file mode 100644 index 00000000..ce7972ad --- /dev/null +++ b/Software/src/devboard/webserver/cellmonitor_html.h @@ -0,0 +1,17 @@ +#ifndef CELLMONITOR_H +#define CELLMONITOR_H + +extern uint16_t cell_max_voltage; //mV, 0-4350 +extern uint16_t cell_min_voltage; //mV, 0-4350 +extern uint16_t cellvoltages[120]; //mV 0-4350 per cell + +/** + * @brief Replaces placeholder with content section in web page + * + * @param[in] var + * + * @return String + */ +String cellmonitor_processor(const String& var); + +#endif diff --git a/Software/src/devboard/webserver/events_html.cpp b/Software/src/devboard/webserver/events_html.cpp new file mode 100644 index 00000000..0879dcc8 --- /dev/null +++ b/Software/src/devboard/webserver/events_html.cpp @@ -0,0 +1,53 @@ +#include "events_html.h" +#include + +const char EVENTS_HTML_START[] = R"=====( + +
+

Event log:

+
+
+
Event Type
LED Color
Last Event (seconds ago)
Count
Data
Message
+
+)====="; +const char EVENTS_HTML_END[] = R"=====( +
+ + +)====="; + +String events_processor(const String& var) { + if (var == "PLACEHOLDER") { + String content = ""; + content.reserve(5000); + // Page format + content.concat(FPSTR(EVENTS_HTML_START)); + for (int i = 0; i < EVENT_NOF_EVENTS; i++) { + Serial.println("Event: " + String(get_event_enum_string(static_cast(i))) + + " count: " + String(entries[i].occurences) + " seconds: " + String(entries[i].timestamp) + + " data: " + String(entries[i].data)); + if (entries[i].occurences > 0) { + content.concat("
"); + content.concat("
" + String(get_event_enum_string(static_cast(i))) + "
"); + content.concat("
" + String(get_led_color_display_text(entries[i].led_color)) + "
"); + content.concat("
" + String((millis() / 1000) - entries[i].timestamp) + "
"); + content.concat("
" + String(entries[i].occurences) + "
"); + content.concat("
" + String(entries[i].data) + "
"); + content.concat("
" + String(get_event_message(static_cast(i))) + "
"); + content.concat("
"); // End of event row + } + } + content.concat(FPSTR(EVENTS_HTML_END)); + return content; + } + return String(); +} diff --git a/Software/src/devboard/webserver/events_html.h b/Software/src/devboard/webserver/events_html.h new file mode 100644 index 00000000..a13f9b0c --- /dev/null +++ b/Software/src/devboard/webserver/events_html.h @@ -0,0 +1,17 @@ +#ifndef EVENTS_H +#define EVENTS_H + +#include "../utils/events.h" + +extern EVENTS_STRUCT_TYPE entries[EVENT_NOF_EVENTS]; + +/** + * @brief Replaces placeholder with content section in web page + * + * @param[in] var + * + * @return String + */ +String events_processor(const String& var); + +#endif diff --git a/Software/src/devboard/webserver/index_html.cpp b/Software/src/devboard/webserver/index_html.cpp new file mode 100644 index 00000000..51bd5bd5 --- /dev/null +++ b/Software/src/devboard/webserver/index_html.cpp @@ -0,0 +1,26 @@ +const char index_html[] = R"rawliteral( + + + Battery Emulator + + + + + +

Battery Emulator

+ %PLACEHOLDER% + + + +)rawliteral"; diff --git a/Software/src/devboard/webserver/settings_html.cpp b/Software/src/devboard/webserver/settings_html.cpp new file mode 100644 index 00000000..35cbd113 --- /dev/null +++ b/Software/src/devboard/webserver/settings_html.cpp @@ -0,0 +1,238 @@ +#include "settings_html.h" +#include + +String settings_processor(const String& var) { + if (var == "PLACEHOLDER") { + String content = ""; + //Page format + content += ""; + + // Start a new block with a specific background color + content += "
"; + + // Show current settings with edit buttons and input fields + content += "

Battery capacity: " + String(BATTERY_WH_MAX) + + " Wh

"; + content += "

SOC max percentage: " + String(MAXPERCENTAGE / 10.0, 1) + + "

"; + content += "

SOC min percentage: " + String(MINPERCENTAGE / 10.0, 1) + + "

"; + content += "

Max charge speed: " + String(MAXCHARGEAMP / 10.0, 1) + + " A

"; + content += "

Max discharge speed: " + String(MAXDISCHARGEAMP / 10.0, 1) + + " A

"; + // Close the block + content += "
"; + +#ifdef TEST_FAKE_BATTERY + // Start a new block with blue background color + content += "
"; + float voltageFloat = static_cast(battery_voltage) / 10.0; // Convert to float and divide by 10 + content += "

Fake battery voltage: " + String(voltageFloat, 1) + + " V

"; + + // Close the block + content += "
"; +#endif + +#if defined CHEVYVOLT_CHARGER || defined NISSANLEAF_CHARGER + + // Start a new block with orange background color + content += "
"; + + content += "

Charger HVDC Enabled: "; + if (charger_HV_enabled) { + content += ""; + } else { + content += ""; + } + content += "

"; + + content += "

Charger Aux12VDC Enabled: "; + if (charger_aux12V_enabled) { + content += ""; + } else { + content += ""; + } + content += "

"; + + content += "

Charger Voltage Setpoint: " + String(charger_setpoint_HV_VDC, 1) + + " V

"; + content += "

Charger Current Setpoint: " + String(charger_setpoint_HV_IDC, 1) + + " A

"; + + // Close the block + content += "
"; +#endif + + content += ""; + + content += ""; + content += ""; + return content; + } + return String(); +} diff --git a/Software/src/devboard/webserver/settings_html.h b/Software/src/devboard/webserver/settings_html.h new file mode 100644 index 00000000..fe466842 --- /dev/null +++ b/Software/src/devboard/webserver/settings_html.h @@ -0,0 +1,16 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "../../../USER_SETTINGS.h" // Needed for WiFi ssid and password +extern uint16_t battery_voltage; //V+1, 0-500.0 (0-5000) + +/** + * @brief Replaces placeholder with content section in web page + * + * @param[in] var + * + * @return String + */ +String settings_processor(const String& var); + +#endif diff --git a/Software/src/devboard/webserver/webserver.cpp b/Software/src/devboard/webserver/webserver.cpp index 8d7aa1ab..16bd556b 100644 --- a/Software/src/devboard/webserver/webserver.cpp +++ b/Software/src/devboard/webserver/webserver.cpp @@ -1,40 +1,16 @@ #include "webserver.h" #include -Preferences preferences3; - // Create AsyncWebServer object on port 80 AsyncWebServer server(80); // Measure OTA progress unsigned long ota_progress_millis = 0; -const char index_html[] PROGMEM = R"rawliteral( - - - Battery Emulator - - - - - -

Battery Emulator

- %PLACEHOLDER% - - - -)rawliteral"; +#include "cellmonitor_html.h" +#include "events_html.h" +#include "index_html.cpp" +#include "settings_html.h" enum WifiState { INIT, //before connecting first time @@ -62,6 +38,8 @@ void init_webserver() { } init_WiFi_STA(ssid, password, wifi_channel); + String content = index_html; + // Route for root / web page server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send_P(200, "text/html", index_html, processor); }); @@ -75,10 +53,9 @@ void init_webserver() { request->send_P(200, "text/html", index_html, cellmonitor_processor); }); -#ifdef EVENTLOGGING + // Route for going to event log web page server.on("/events", HTTP_GET, [](AsyncWebServerRequest* request) { request->send_P(200, "text/html", index_html, events_processor); }); -#endif // Route for editing Wh server.on("/updateBatterySize", HTTP_GET, [](AsyncWebServerRequest* request) { @@ -629,9 +606,7 @@ String processor(const String& var) { content += "function goToUpdatePage() { window.location.href = '/update'; }"; content += "function goToCellmonitorPage() { window.location.href = '/cellmonitor'; }"; content += "function goToSettingsPage() { window.location.href = '/settings'; }"; -#ifdef EVENTLOGGING content += "function goToEventsPage() { window.location.href = '/events'; }"; -#endif content += "function promptToReboot() { if (window.confirm('Are you sure you want to reboot the emulator? NOTE: If " "emulator is handling contactors, they will open during reboot!')) { " @@ -653,348 +628,6 @@ String processor(const String& var) { return String(); } -String settings_processor(const String& var) { - if (var == "PLACEHOLDER") { - String content = ""; - //Page format - content += ""; - - // Start a new block with a specific background color - content += "
"; - - // Show current settings with edit buttons and input fields - content += "

Battery capacity: " + String(BATTERY_WH_MAX) + - " Wh

"; - content += "

SOC max percentage: " + String(MAXPERCENTAGE / 10.0, 1) + - "

"; - content += "

SOC min percentage: " + String(MINPERCENTAGE / 10.0, 1) + - "

"; - content += "

Max charge speed: " + String(MAXCHARGEAMP / 10.0, 1) + - " A

"; - content += "

Max discharge speed: " + String(MAXDISCHARGEAMP / 10.0, 1) + - " A

"; - // Close the block - content += "
"; - -#ifdef TEST_FAKE_BATTERY - // Start a new block with blue background color - content += "
"; - float voltageFloat = static_cast(battery_voltage) / 10.0; // Convert to float and divide by 10 - content += "

Fake battery voltage: " + String(voltageFloat, 1) + - " V

"; - - // Close the block - content += "
"; -#endif - -#if defined CHEVYVOLT_CHARGER || defined NISSANLEAF_CHARGER - - // Start a new block with orange background color - content += "
"; - - content += "

Charger HVDC Enabled: "; - if (charger_HV_enabled) { - content += ""; - } else { - content += ""; - } - content += "

"; - - content += "

Charger Aux12VDC Enabled: "; - if (charger_aux12V_enabled) { - content += ""; - } else { - content += ""; - } - content += "

"; - - content += "

Charger Voltage Setpoint: " + String(charger_setpoint_HV_VDC, 1) + - " V

"; - content += "

Charger Current Setpoint: " + String(charger_setpoint_HV_IDC, 1) + - " A

"; - - // Close the block - content += "
"; -#endif - - content += ""; - - content += ""; - content += ""; - return content; - } - return String(); -} - -String cellmonitor_processor(const String& var) { - if (var == "PLACEHOLDER") { - String content = ""; - // Page format - content += ""; - - // Start a new block with a specific background color - content += "
"; - - // Display max, min, and deviation voltage values - content += "
"; - content += "Max Voltage: " + String(cell_max_voltage) + " mV
"; - content += "Min Voltage: " + String(cell_min_voltage) + " mV
"; - int deviation = cell_max_voltage - cell_min_voltage; - content += "Voltage Deviation: " + String(deviation) + " mV"; - content += "
"; - - // Visualize the populated cells in forward order using flexbox with conditional text color - content += "
"; - for (int i = 0; i < 120; ++i) { - // Skip empty values - if (cellvoltages[i] == 0) { - continue; - } - - String cellContent = "Cell " + String(i + 1) + "
" + String(cellvoltages[i]) + " mV"; - - // Check if the cell voltage is below 3000, apply red color - if (cellvoltages[i] < 3000) { - cellContent = "" + cellContent + ""; - } - - content += "
" + cellContent + "
"; - } - content += "
"; - - // Close the block - content += "
"; - - content += ""; - content += ""; - return content; - } - return String(); -} - -#ifdef EVENTLOGGING -const char EVENTS_HTML_START[] PROGMEM = R"=====( - -
-

Event log:

-
-
-
Event Type
LED Color
Last Event (seconds ago)
Count
Data
Message
-
-)====="; -const char EVENTS_HTML_END[] PROGMEM = R"=====( -
- - -)====="; - -String events_processor(const String& var) { - if (var == "PLACEHOLDER") { - String content = ""; - content.reserve(5000); - // Page format - content.concat(FPSTR(EVENTS_HTML_START)); - for (int i = 0; i < EVENT_NOF_EVENTS; i++) { - Serial.println("Event: " + String(get_event_enum_string(static_cast(i))) + - " count: " + String(entries[i].occurences) + " seconds: " + String(entries[i].timestamp) + - " data: " + String(entries[i].data)); - if (entries[i].occurences > 0) { - content.concat("
"); - content.concat("
" + String(get_event_enum_string(static_cast(i))) + "
"); - content.concat("
" + String(get_led_color_display_text(entries[i].led_color)) + "
"); - content.concat("
" + String((millis() / 1000) - entries[i].timestamp) + "
"); - content.concat("
" + String(entries[i].occurences) + "
"); - content.concat("
" + String(entries[i].data) + "
"); - content.concat("
" + String(get_event_message(static_cast(i))) + "
"); - content.concat("
"); // End of event row - } - } - content.concat(FPSTR(EVENTS_HTML_END)); - return content; - } - return String(); -} -#endif void onOTAStart() { // Log when OTA has started Serial.println("OTA update started!"); diff --git a/Software/src/devboard/webserver/webserver.h b/Software/src/devboard/webserver/webserver.h index c874b728..23b65278 100644 --- a/Software/src/devboard/webserver/webserver.h +++ b/Software/src/devboard/webserver/webserver.h @@ -12,7 +12,6 @@ #include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h" #include "../../lib/miwagner-ESP32-Arduino-CAN/ESP32CAN.h" #include "../config.h" // Needed for LED defines -#include "../utils/events.h" #ifdef MQTT #include "../mqtt/mqtt.h" #endif @@ -37,7 +36,6 @@ extern uint16_t cellvoltages[120]; //mV 0-4350 per cell extern uint8_t LEDcolor; //Enum, 0-10 extern bool batteryAllowsContactorClosing; //Bool, 1=true, 0=false extern bool inverterAllowsContactorClosing; //Bool, 1=true, 0=false -extern EVENTS_STRUCT_TYPE entries[EVENT_NOF_EVENTS]; extern const char* ssid; extern const char* password; @@ -120,33 +118,6 @@ void init_ElegantOTA(); */ String processor(const String& var); -/** - * @brief Replaces placeholder with content section in web page - * - * @param[in] var - * - * @return String - */ -String settings_processor(const String& var); - -/** - * @brief Replaces placeholder with content section in web page - * - * @param[in] var - * - * @return String - */ -String cellmonitor_processor(const String& var); - -/** - * @brief Replaces placeholder with content section in web page - * - * @param[in] var - * - * @return String - */ -String events_processor(const String& var); - /** * @brief Executes on OTA start *