-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feature/double-lilygo
- Loading branch information
Showing
98 changed files
with
14,611 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# Ignore any .vscode folder | ||
*.vscode/ | ||
|
||
# Ignore any files in the build folder | ||
Software/build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#include "USER_SETTINGS.h" | ||
|
||
#ifdef WEBSERVER | ||
const char* ssid = "REPLACE_WITH_YOUR_SSID"; // maximum of 63 characters; | ||
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 | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Battery Emulator Webserver | ||
This webserver creates a WiFi access point. It also connects ot an existing network. | ||
The webserver intends to display useful information to the user of the battery emulator | ||
development board, without the need to physically connect to the board via USB. | ||
The webserver implementation also provides the option to update the firmware of the board over the air. | ||
|
||
To use the webserver, follow the following steps: | ||
- Connect to the board via Serial, and boot up the board. | ||
- The IP address of the WiFi access point is printed to Serial when the board boots up. Note this down. | ||
- Connect to the access point created by board via a WiFi-capable device | ||
- On that device, open a webbrowser and type the IP address of the WiFi access point. | ||
- If the ssid and password of an existing WiFi network are provided, the board will also connect to this network. The IP address obtained on the existing network is shown in the webserver. Note this down. | ||
- From this point onwards, any device connected to the existing WiFi network can access the webserver via a webbrowser. To do this: | ||
- Connect your WiFi-capable device to the existing nwetork. | ||
- Open a webbrowser and type the IP address obtained on the existing WiFi network. | ||
|
||
To update the software over the air: | ||
- In Arduino, go to `Sketch` > `Export Compiled Binary`. This will create the `.bin` file that you need to update the firmware. It is found in the folder `Software/build/` | ||
- In your webbrowser, go to the url consisting of the IP address, followed by `/update`, for instance `http://192.168.0.224/update`. | ||
- In the webbrowser, follow the steps to select the `.bin` file and to upload the file to the board. | ||
|
||
## Future work | ||
This section lists a number of features that can be implemented as part of the webserver in the future. | ||
|
||
- TODO: display state of charge | ||
- TODO: display battery hardware selected | ||
- TODO: display emulated inverter communication protocol selected | ||
- TODO: list all available ssids: scan WiFi Networks https://randomnerdtutorials.com/esp32-useful-wi-fi-functions-arduino/ | ||
- TODO: add option to add/change ssid and password and save, connect to the new ssid (Option: save ssid and password using Preferences.h library https://randomnerdtutorials.com/esp32-save-data-permanently-preferences/) | ||
- TODO: display WiFi connection strength (https://randomnerdtutorials.com/esp32-useful-wi-fi-functions-arduino/) | ||
- TODO: display CAN state (indicate if there is a communication error) | ||
- TODO: display battery errors in battery diagnosis tab | ||
- TODO: display inverter errors in battery diagnosis tab | ||
- TODO: add functionality to turn WiFi AP off | ||
- TODO: fix IP address on home network (https://randomnerdtutorials.com/esp32-static-fixed-ip-address-arduino-ide/) | ||
- TODO: set hostname (https://randomnerdtutorials.com/esp32-set-custom-hostname-arduino/) | ||
|
||
# References | ||
The code for this webserver is based on code provided by Rui Santos at https://randomnerdtutorials.com. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
#include "webserver.h" | ||
|
||
// 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( | ||
<!DOCTYPE HTML><html> | ||
<head> | ||
<title>Battery Emulator Web Server</title> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="icon" href="data:,"> | ||
<style> | ||
html {font-family: Arial; display: inline-block; text-align: center;} | ||
h2 {font-size: 3.0rem;} | ||
p {font-size: 3.0rem;} | ||
body {max-width: 600px; margin:0px auto; padding-bottom: 25px;} | ||
.switch {position: relative; display: inline-block; width: 120px; height: 68px} | ||
.switch input {display: none} | ||
.slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px} | ||
.slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px} | ||
input:checked+.slider {background-color: #b30000} | ||
input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)} | ||
</style> | ||
</head> | ||
<body> | ||
<h2>Battery Emulator Web Server</h2> | ||
%PLACEHOLDER% | ||
</script> | ||
</body> | ||
</html> | ||
)rawliteral"; | ||
|
||
String wifi_state; | ||
bool wifi_connected; | ||
|
||
// Wifi connect time declarations and definition | ||
unsigned long wifi_connect_start_time; | ||
unsigned long wifi_connect_current_time; | ||
const long wifi_connect_timeout = 5000; // Timeout for WiFi connect in milliseconds | ||
|
||
void init_webserver() { | ||
// Configure WiFi | ||
WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi Access Point and WiFi STAtion | ||
init_WiFi_AP(); | ||
init_WiFi_STA(ssid, password); | ||
|
||
// Route for root / web page | ||
server.on("/", HTTP_GET, | ||
[](AsyncWebServerRequest* request) { request->send_P(200, "text/html", index_html, processor); }); | ||
|
||
// Send a GET request to <ESP_IP>/update | ||
server.on("/debug", HTTP_GET, | ||
[](AsyncWebServerRequest* request) { request->send(200, "text/plain", "Debug: all OK."); }); | ||
|
||
// Initialize ElegantOTA | ||
init_ElegantOTA(); | ||
|
||
// Start server | ||
server.begin(); | ||
} | ||
|
||
void init_WiFi_AP() { | ||
Serial.print("Creating Access Point: "); | ||
Serial.println(ssidAP); | ||
Serial.print("With password: "); | ||
Serial.println(passwordAP); | ||
|
||
WiFi.softAP(ssidAP, passwordAP); | ||
|
||
IPAddress IP = WiFi.softAPIP(); | ||
Serial.println("Access Point created."); | ||
Serial.print("IP address: "); | ||
Serial.println(IP); | ||
} | ||
|
||
void init_WiFi_STA(const char* ssid, const char* password) { | ||
// Connect to Wi-Fi network with SSID and password | ||
Serial.print("Connecting to "); | ||
Serial.println(ssid); | ||
WiFi.begin(ssid, password); | ||
|
||
wifi_connect_start_time = millis(); | ||
wifi_connect_current_time = wifi_connect_start_time; | ||
while ((wifi_connect_current_time - wifi_connect_start_time) <= wifi_connect_timeout && | ||
WiFi.status() != WL_CONNECTED) { // do this loop for up to 5000ms | ||
// to break the loop when the connection is not established (wrong ssid or password). | ||
delay(500); | ||
Serial.print("."); | ||
wifi_connect_current_time = millis(); | ||
} | ||
if (WiFi.status() == WL_CONNECTED) { // WL_CONNECTED is assigned when connected to a WiFi network | ||
wifi_connected = true; | ||
wifi_state = "connected"; | ||
// Print local IP address and start web server | ||
Serial.println(""); | ||
Serial.print("Connected to WiFi network: "); | ||
Serial.println(ssid); | ||
Serial.print("IP address: "); | ||
Serial.println(WiFi.localIP()); | ||
} else { | ||
wifi_connected = false; | ||
wifi_state = "not connected"; | ||
Serial.print("Not connected to WiFi network: "); | ||
Serial.println(ssid); | ||
Serial.println("Please check WiFi network name and password, and if WiFi network is available."); | ||
} | ||
} | ||
|
||
void init_ElegantOTA() { | ||
ElegantOTA.begin(&server); // Start ElegantOTA | ||
// ElegantOTA callbacks | ||
ElegantOTA.onStart(onOTAStart); | ||
ElegantOTA.onProgress(onOTAProgress); | ||
ElegantOTA.onEnd(onOTAEnd); | ||
} | ||
|
||
String processor(const String& var) { | ||
if (var == "PLACEHOLDER") { | ||
String content = ""; | ||
// Display LED color | ||
content += "<h4>LED color: "; | ||
switch (LEDcolor) { | ||
case GREEN: | ||
content += "GREEN</h4>"; | ||
break; | ||
case YELLOW: | ||
content += "YELLOW</h4>"; | ||
break; | ||
case BLUE: | ||
content += "BLUE</h4>"; | ||
break; | ||
case RED: | ||
content += "RED</h4>"; | ||
break; | ||
case TEST_ALL_COLORS: | ||
content += "RAINBOW</h4>"; | ||
break; | ||
default: | ||
break; | ||
} | ||
// Display ssid of network connected to and, if connected to the WiFi, its own IP | ||
content += "<h4>SSID: " + String(ssid) + "</h4>"; | ||
content += "<h4>status: " + wifi_state + "</h4>"; | ||
if (wifi_connected == true) { | ||
content += "<h4>IP: " + WiFi.localIP().toString() + "</h4>"; | ||
} | ||
return content; | ||
} | ||
return String(); | ||
} | ||
|
||
void onOTAStart() { | ||
// Log when OTA has started | ||
Serial.println("OTA update started!"); | ||
// <Add your own code here> | ||
} | ||
|
||
void onOTAProgress(size_t current, size_t final) { | ||
// Log every 1 second | ||
if (millis() - ota_progress_millis > 1000) { | ||
ota_progress_millis = millis(); | ||
Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final); | ||
} | ||
} | ||
|
||
void onOTAEnd(bool success) { | ||
// Log when OTA has finished | ||
if (success) { | ||
Serial.println("OTA update finished successfully!"); | ||
} else { | ||
Serial.println("There was an error during OTA update!"); | ||
} | ||
// <Add your own code here> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#ifndef WEBSERVER_H | ||
#define WEBSERVER_H | ||
|
||
// Load Wi-Fi library | ||
#include <WiFi.h> | ||
#include "../../../USER_SETTINGS.h" // Needed for WiFi ssid and password | ||
#include "../../lib/ayushsharma82-ElegantOTA/src/ElegantOTA.h" | ||
#include "../../lib/me-no-dev-AsyncTCP/src/AsyncTCP.h" | ||
#include "../../lib/me-no-dev-ESPAsyncWebServer/src/ESPAsyncWebServer.h" | ||
#include "../config.h" // Needed for LED defines | ||
|
||
extern uint8_t LEDcolor; // Enum, 0-10 | ||
extern const char* ssid; | ||
extern const char* password; | ||
extern const char* ssidAP; | ||
extern const char* passwordAP; | ||
|
||
/** | ||
* @brief Initialization function for the webserver. | ||
* | ||
* @param[in] void | ||
* | ||
* @return void | ||
*/ | ||
void init_webserver(); | ||
|
||
/** | ||
* @brief Initialization function that creates a WiFi Access Point. | ||
* | ||
* @param[in] void | ||
* | ||
* @return void | ||
*/ | ||
void init_WiFi_AP(); | ||
|
||
/** | ||
* @brief Initialization function that connects to an existing network. | ||
* | ||
* @param[in] ssid WiFi network name | ||
* @param[in] password WiFi network password | ||
* | ||
* @return void | ||
*/ | ||
void init_WiFi_STA(const char* ssid, const char* password); | ||
|
||
/** | ||
* @brief Initialization function for ElegantOTA. | ||
* | ||
* @param[in] void | ||
* | ||
* @return void | ||
*/ | ||
void init_ElegantOTA(); | ||
|
||
/** | ||
* @brief Replaces placeholder with content section in web page | ||
* | ||
* @param[in] var | ||
* | ||
* @return String | ||
*/ | ||
String processor(const String& var); | ||
|
||
/** | ||
* @brief Executes on OTA start | ||
* | ||
* @param[in] void | ||
* | ||
* @return void | ||
*/ | ||
void onOTAStart(); | ||
|
||
/** | ||
* @brief Executes on OTA progress | ||
* | ||
* @param[in] current Current bytes | ||
* @param[in] final Final bytes | ||
* | ||
* @return void | ||
*/ | ||
void onOTAProgress(size_t current, size_t final); | ||
|
||
/** | ||
* @brief Executes on OTA end | ||
* | ||
* @param[in] void | ||
* | ||
* @return bool success: success = true, failed = false | ||
*/ | ||
void onOTAEnd(bool success); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.