mirror of
https://github.com/dalathegreat/Battery-Emulator.git
synced 2025-10-03 17:59:27 +02:00
Wifi settings for common image
This commit is contained in:
parent
0b73436d3d
commit
5d86058852
9 changed files with 254 additions and 384 deletions
|
@ -21,14 +21,26 @@ volatile CAN_Configuration can_config = {
|
||||||
.shunt = CAN_NATIVE // (OPTIONAL) Which CAN is your shunt connected to?
|
.shunt = CAN_NATIVE // (OPTIONAL) Which CAN is your shunt connected to?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
std::string ssid;
|
||||||
|
std::string password;
|
||||||
|
std::string passwordAP;
|
||||||
|
#else
|
||||||
std::string ssid = WIFI_SSID; // Set in USER_SECRETS.h
|
std::string ssid = WIFI_SSID; // Set in USER_SECRETS.h
|
||||||
std::string password = WIFI_PASSWORD; // Set in USER_SECRETS.h
|
std::string password = WIFI_PASSWORD; // Set in USER_SECRETS.h
|
||||||
const char* ssidAP = "Battery Emulator"; // Maximum of 63 characters, also used for device name on web interface
|
std::string passwordAP = AP_PASSWORD; // Set in USER_SECRETS.h
|
||||||
const char* passwordAP = AP_PASSWORD; // Set in USER_SECRETS.h
|
#endif
|
||||||
|
|
||||||
const uint8_t wifi_channel = 0; // Set to 0 for automatic channel selection
|
const uint8_t wifi_channel = 0; // Set to 0 for automatic channel selection
|
||||||
|
|
||||||
const char* http_username = HTTP_USERNAME; // Set in USER_SECRETS.h
|
#ifdef COMMON_IMAGE
|
||||||
const char* http_password = HTTP_PASSWORD; // Set in USER_SECRETS.h
|
std::string http_username;
|
||||||
|
std::string http_password;
|
||||||
|
#else
|
||||||
|
std::string http_username = HTTP_USERNAME; // Set in USER_SECRETS.h
|
||||||
|
std::string http_password = HTTP_PASSWORD; // Set in USER_SECRETS.h
|
||||||
|
#endif
|
||||||
|
|
||||||
// Set your Static IP address. Only used incase WIFICONFIG is set in USER_SETTINGS.h
|
// Set your Static IP address. Only used incase WIFICONFIG is set in USER_SETTINGS.h
|
||||||
IPAddress local_IP(192, 168, 10, 150);
|
IPAddress local_IP(192, 168, 10, 150);
|
||||||
IPAddress gateway(192, 168, 10, 1);
|
IPAddress gateway(192, 168, 10, 1);
|
||||||
|
|
|
@ -51,6 +51,8 @@ ACAN2517FDSettings* settings2517;
|
||||||
|
|
||||||
// Initialization functions
|
// Initialization functions
|
||||||
|
|
||||||
|
bool native_can_initialized = false;
|
||||||
|
|
||||||
bool init_CAN() {
|
bool init_CAN() {
|
||||||
|
|
||||||
auto nativeIt = can_receivers.find(CAN_NATIVE);
|
auto nativeIt = can_receivers.find(CAN_NATIVE);
|
||||||
|
@ -82,6 +84,7 @@ bool init_CAN() {
|
||||||
CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));
|
CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));
|
||||||
// Init CAN Module
|
// Init CAN Module
|
||||||
ESP32Can.CANInit();
|
ESP32Can.CANInit();
|
||||||
|
native_can_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto addonIt = can_receivers.find(CAN_ADDON_MCP2515);
|
auto addonIt = can_receivers.find(CAN_ADDON_MCP2515);
|
||||||
|
@ -260,7 +263,9 @@ void transmit_can_frame(CAN_frame* tx_frame, int interface) {
|
||||||
|
|
||||||
// Receive functions
|
// Receive functions
|
||||||
void receive_can() {
|
void receive_can() {
|
||||||
|
if (native_can_initialized) {
|
||||||
receive_frame_can_native(); // Receive CAN messages from native CAN port
|
receive_frame_can_native(); // Receive CAN messages from native CAN port
|
||||||
|
}
|
||||||
|
|
||||||
if (can2515) {
|
if (can2515) {
|
||||||
receive_frame_can_addon(); // Receive CAN messages on add-on MCP2515 chip
|
receive_frame_can_addon(); // Receive CAN messages on add-on MCP2515 chip
|
||||||
|
|
|
@ -111,7 +111,9 @@ void init_stored_settings() {
|
||||||
remote_bms_reset = settings.getBool("REMBMSRESET", false);
|
remote_bms_reset = settings.getBool("REMBMSRESET", false);
|
||||||
use_canfd_as_can = settings.getBool("CANFDASCAN", false);
|
use_canfd_as_can = settings.getBool("CANFDASCAN", false);
|
||||||
|
|
||||||
wifiap_enabled = settings.getBool("WIFIAPENABLED", false);
|
// WIFI AP is enabled by default unless disabled in the settings
|
||||||
|
wifiap_enabled = settings.getBool("WIFIAPENABLED", true);
|
||||||
|
passwordAP = settings.getString("APPASSWORD", "123456789").c_str();
|
||||||
mqtt_enabled = settings.getBool("MQTTENABLED", false);
|
mqtt_enabled = settings.getBool("MQTTENABLED", false);
|
||||||
ha_autodiscovery_enabled = settings.getBool("HADISC", false);
|
ha_autodiscovery_enabled = settings.getBool("HADISC", false);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,11 @@ class BatteryEmulatorSettingsStore {
|
||||||
|
|
||||||
~BatteryEmulatorSettingsStore() { settings.end(); }
|
~BatteryEmulatorSettingsStore() { settings.end(); }
|
||||||
|
|
||||||
|
void clearAll() {
|
||||||
|
settings.clear();
|
||||||
|
settingsUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t getUInt(const char* name, uint32_t defaultValue) { return settings.getUInt(name, defaultValue); }
|
uint32_t getUInt(const char* name, uint32_t defaultValue) { return settings.getUInt(name, defaultValue); }
|
||||||
|
|
||||||
void saveUInt(const char* name, uint32_t value) {
|
void saveUInt(const char* name, uint32_t value) {
|
||||||
|
@ -56,7 +61,9 @@ class BatteryEmulatorSettingsStore {
|
||||||
settingsUpdated = settingsUpdated || value != oldValue;
|
settingsUpdated = settingsUpdated || value != oldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getBool(const char* name) { return settings.getBool(name, false); }
|
bool settingExists(const char* name) { return settings.isKey(name); }
|
||||||
|
|
||||||
|
bool getBool(const char* name, bool defaultValue = false) { return settings.getBool(name, defaultValue); }
|
||||||
|
|
||||||
void saveBool(const char* name, bool value) {
|
void saveBool(const char* name, bool value) {
|
||||||
auto oldValue = settings.getBool(name, false);
|
auto oldValue = settings.getBool(name, false);
|
||||||
|
|
|
@ -217,7 +217,7 @@ String settings_processor(const String& var, BatteryEmulatorSettingsStore& setti
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == "WIFIAPENABLED") {
|
if (var == "WIFIAPENABLED") {
|
||||||
return settings.getBool("WIFIAPENABLED") ? "checked" : "";
|
return settings.getBool("WIFIAPENABLED", wifiap_enabled) ? "checked" : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == "MQTTENABLED") {
|
if (var == "MQTTENABLED") {
|
||||||
|
@ -435,6 +435,26 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
||||||
#define SETTINGS_HTML_SCRIPTS \
|
#define SETTINGS_HTML_SCRIPTS \
|
||||||
R"rawliteral(
|
R"rawliteral(
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
function askFactoryReset() {
|
||||||
|
if (confirm('Are you sure you want to reset the device to factory settings? This will erase all settings and data.')) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (this.status == 200) {
|
||||||
|
alert('Factory reset successful. The device will now restart.');
|
||||||
|
reboot();
|
||||||
|
} else {
|
||||||
|
alert('Factory reset failed. Please try again.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function() {
|
||||||
|
alert('An error occurred while trying to reset the device.');
|
||||||
|
};
|
||||||
|
xhr.open('POST', '/factoryReset', true);
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function editComplete(){if(this.status==200){window.location.reload();}}
|
function editComplete(){if(this.status==200){window.location.reload();}}
|
||||||
|
|
||||||
function editError(){alert('Invalid input');}
|
function editError(){alert('Invalid input');}
|
||||||
|
@ -725,6 +745,7 @@ const char* getCANInterfaceName(CAN_Interface interface) {
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button onclick="askFactoryReset()">Factory reset</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
#include "../utils/timer.h"
|
#include "../utils/timer.h"
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
extern std::string http_username;
|
||||||
|
extern std::string http_password;
|
||||||
|
|
||||||
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
void transmit_can_frame(CAN_frame* tx_frame, int interface);
|
||||||
|
|
||||||
#ifdef WEBSERVER
|
#ifdef WEBSERVER
|
||||||
|
@ -26,6 +30,14 @@ const bool webserver_enabled_default = false;
|
||||||
|
|
||||||
bool webserver_enabled = webserver_enabled_default; // Global flag to enable or disable the webserver
|
bool webserver_enabled = webserver_enabled_default; // Global flag to enable or disable the webserver
|
||||||
|
|
||||||
|
#ifndef COMMON_IMAGE
|
||||||
|
const bool webserver_auth_default = WEBSERVER_AUTH_REQUIRED;
|
||||||
|
#else
|
||||||
|
const bool webserver_auth_default = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool webserver_auth = webserver_auth_default;
|
||||||
|
|
||||||
// Create AsyncWebServer object on port 80
|
// Create AsyncWebServer object on port 80
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
|
|
||||||
|
@ -167,30 +179,31 @@ void canReplayTask(void* param) {
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void def_route_with_auth(const char* uri, AsyncWebServer& serv, WebRequestMethodComposite method,
|
||||||
|
std::function<void(AsyncWebServerRequest*)> handler) {
|
||||||
|
serv.on(uri, method, [handler](AsyncWebServerRequest* request) {
|
||||||
|
if (webserver_auth && !request->authenticate(http_username.c_str(), http_password.c_str())) {
|
||||||
|
return request->requestAuthentication();
|
||||||
|
}
|
||||||
|
handler(request);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void init_webserver() {
|
void init_webserver() {
|
||||||
|
|
||||||
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(401); });
|
server.on("/logout", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(401); });
|
||||||
|
|
||||||
// Route for firmware info from ota update page
|
// Route for firmware info from ota update page
|
||||||
server.on("/GetFirmwareInfo", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/GetFirmwareInfo", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "application/json", get_firmware_info_html, get_firmware_info_processor);
|
request->send(200, "application/json", get_firmware_info_html, get_firmware_info_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for root / web page
|
// Route for root / web page
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/", server, HTTP_GET,
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](AsyncWebServerRequest* request) { request->send(200, "text/html", index_html, processor); });
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/html", index_html, processor);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for going to settings web page
|
// Route for going to settings web page
|
||||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/settings", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
|
|
||||||
return request->requestAuthentication();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using make_shared to ensure lifetime for the settings object during send() lambda execution
|
// Using make_shared to ensure lifetime for the settings object during send() lambda execution
|
||||||
auto settings = std::make_shared<BatteryEmulatorSettingsStore>(true);
|
auto settings = std::make_shared<BatteryEmulatorSettingsStore>(true);
|
||||||
|
|
||||||
|
@ -199,30 +212,21 @@ void init_webserver() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to advanced battery info web page
|
// Route for going to advanced battery info web page
|
||||||
server.on("/advanced", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/advanced", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
request->send(200, "text/html", index_html, advanced_battery_processor);
|
request->send(200, "text/html", index_html, advanced_battery_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to CAN logging web page
|
// Route for going to CAN logging web page
|
||||||
server.on("/canlog", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/canlog", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
AsyncWebServerResponse* response = request->beginResponse(200, "text/html", can_logger_processor());
|
request->send(request->beginResponse(200, "text/html", can_logger_processor()));
|
||||||
request->send(response);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to CAN replay web page
|
// Route for going to CAN replay web page
|
||||||
server.on("/canreplay", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/canreplay", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
|
request->send(request->beginResponse(200, "text/html", can_replay_processor()));
|
||||||
return request->requestAuthentication();
|
|
||||||
}
|
|
||||||
AsyncWebServerResponse* response = request->beginResponse(200, "text/html", can_replay_processor());
|
|
||||||
request->send(response);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/startReplay", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/startReplay", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
|
|
||||||
return request->requestAuthentication();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent multiple replay tasks from being created
|
// Prevent multiple replay tasks from being created
|
||||||
if (isReplayRunning) {
|
if (isReplayRunning) {
|
||||||
request->send(400, "text/plain", "Replay already running!");
|
request->send(400, "text/plain", "Replay already running!");
|
||||||
|
@ -238,18 +242,14 @@ void init_webserver() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for stopping the CAN replay
|
// Route for stopping the CAN replay
|
||||||
server.on("/stopReplay", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/stopReplay", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
|
|
||||||
return request->requestAuthentication();
|
|
||||||
}
|
|
||||||
|
|
||||||
datalayer.system.info.loop_playback = false;
|
datalayer.system.info.loop_playback = false;
|
||||||
|
|
||||||
request->send(200, "text/plain", "CAN replay stopped!");
|
request->send(200, "text/plain", "CAN replay stopped!");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route to handle setting the CAN interface for CAN replay
|
// Route to handle setting the CAN interface for CAN replay
|
||||||
server.on("/setCANInterface", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/setCANInterface", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (request->hasParam("interface")) {
|
if (request->hasParam("interface")) {
|
||||||
String canInterface = request->getParam("interface")->value();
|
String canInterface = request->getParam("interface")->value();
|
||||||
|
|
||||||
|
@ -377,23 +377,17 @@ void init_webserver() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Route for going to cellmonitor web page
|
// Route for going to cellmonitor web page
|
||||||
server.on("/cellmonitor", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/cellmonitor", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/html", index_html, cellmonitor_processor);
|
request->send(200, "text/html", index_html, cellmonitor_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for going to event log web page
|
// Route for going to event log web page
|
||||||
server.on("/events", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/events", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/html", index_html, events_processor);
|
request->send(200, "text/html", index_html, events_processor);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for clearing all events
|
// Route for clearing all events
|
||||||
server.on("/clearevents", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/clearevents", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
reset_all_events();
|
reset_all_events();
|
||||||
// Send back a response that includes an instant redirect to /events
|
// Send back a response that includes an instant redirect to /events
|
||||||
String response = "<html><body>";
|
String response = "<html><body>";
|
||||||
|
@ -402,6 +396,14 @@ void init_webserver() {
|
||||||
request->send(200, "text/html", response);
|
request->send(200, "text/html", response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
def_route_with_auth("/factoryReset", server, HTTP_POST, [](AsyncWebServerRequest* request) {
|
||||||
|
// Reset all settings to factory defaults
|
||||||
|
BatteryEmulatorSettingsStore settings;
|
||||||
|
settings.clearAll();
|
||||||
|
|
||||||
|
request->send(200, "text/html", "OK");
|
||||||
|
});
|
||||||
|
|
||||||
#ifdef COMMON_IMAGE
|
#ifdef COMMON_IMAGE
|
||||||
struct BoolSetting {
|
struct BoolSetting {
|
||||||
const char* name;
|
const char* name;
|
||||||
|
@ -421,7 +423,7 @@ void init_webserver() {
|
||||||
std::vector<BoolSetting> boolSettings;
|
std::vector<BoolSetting> boolSettings;
|
||||||
|
|
||||||
for (auto& name : boolSettingNames) {
|
for (auto& name : boolSettingNames) {
|
||||||
boolSettings.push_back({name, settings.getBool(name), false});
|
boolSettings.push_back({name, settings.getBool(name, name == std::string("WIFIAPENABLED")), false});
|
||||||
}
|
}
|
||||||
|
|
||||||
int numParams = request->params();
|
int numParams = request->params();
|
||||||
|
@ -495,10 +497,7 @@ void init_webserver() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Route for editing SSID
|
// Route for editing SSID
|
||||||
server.on("/updateSSID", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/updateSSID", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
|
|
||||||
if (request->hasParam("value")) {
|
if (request->hasParam("value")) {
|
||||||
String value = request->getParam("value")->value();
|
String value = request->getParam("value")->value();
|
||||||
if (value.length() <= 63) { // Check if SSID is within the allowable length
|
if (value.length() <= 63) { // Check if SSID is within the allowable length
|
||||||
|
@ -513,9 +512,7 @@ void init_webserver() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Route for editing Password
|
// Route for editing Password
|
||||||
server.on("/updatePassword", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/updatePassword", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
if (request->hasParam("value")) {
|
||||||
String value = request->getParam("value")->value();
|
String value = request->getParam("value")->value();
|
||||||
if (value.length() > 8) { // Check if password is within the allowable length
|
if (value.length() > 8) { // Check if password is within the allowable length
|
||||||
|
@ -530,118 +527,84 @@ void init_webserver() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing Wh
|
auto update_string = [](const char* route, std::function<void(String)> setter,
|
||||||
server.on("/updateBatterySize", HTTP_GET, [](AsyncWebServerRequest* request) {
|
std::function<bool(String)> validator = nullptr) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
def_route_with_auth(route, server, HTTP_GET, [&](AsyncWebServerRequest* request) {
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
if (request->hasParam("value")) {
|
||||||
String value = request->getParam("value")->value();
|
String value = request->getParam("value")->value();
|
||||||
datalayer.battery.info.total_capacity_Wh = value.toInt();
|
|
||||||
store_settings();
|
if (validator && !validator(value)) {
|
||||||
|
request->send(400, "text/plain", "Invalid value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setter(value);
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
request->send(200, "text/plain", "Updated successfully");
|
||||||
} else {
|
} else {
|
||||||
request->send(400, "text/plain", "Bad Request");
|
request->send(400, "text/plain", "Bad Request");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
auto update_string_setting = [=](const char* route, std::function<void(String)> setter,
|
||||||
|
std::function<bool(String)> validator = nullptr) {
|
||||||
|
update_string(
|
||||||
|
route,
|
||||||
|
[setter](String value) {
|
||||||
|
setter(value);
|
||||||
|
store_settings();
|
||||||
|
},
|
||||||
|
validator);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto update_int_setting = [=](const char* route, std::function<void(int)> setter) {
|
||||||
|
update_string_setting(route, [setter](String value) { setter(value.toInt()); });
|
||||||
|
};
|
||||||
|
|
||||||
|
// Route for editing Wh
|
||||||
|
update_int_setting("/updateBatterySize", [](int value) { datalayer.battery.info.total_capacity_Wh = value; });
|
||||||
|
|
||||||
// Route for editing USE_SCALED_SOC
|
// Route for editing USE_SCALED_SOC
|
||||||
server.on("/updateUseScaledSOC", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_int_setting("/updateUseScaledSOC", [](int value) { datalayer.battery.settings.soc_scaling_active = value; });
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.soc_scaling_active = value.toInt();
|
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for editing SOCMax
|
// Route for editing SOCMax
|
||||||
server.on("/updateSocMax", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateSocMax", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.max_percentage = static_cast<uint16_t>(value.toFloat() * 100);
|
datalayer.battery.settings.max_percentage = static_cast<uint16_t>(value.toFloat() * 100);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for pause/resume Battery emulator
|
// Route for pause/resume Battery emulator
|
||||||
server.on("/pause", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string("/pause", [](String value) { setBatteryPause(value == "true" || value == "1", false); });
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("p")) {
|
|
||||||
String valueStr = request->getParam("p")->value();
|
|
||||||
setBatteryPause(valueStr == "true" || valueStr == "1", false);
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for equipment stop/resume
|
// Route for equipment stop/resume
|
||||||
server.on("/equipmentStop", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string("/equipmentStop", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
if (value == "true" || value == "1") {
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("stop")) {
|
|
||||||
String valueStr = request->getParam("stop")->value();
|
|
||||||
if (valueStr == "true" || valueStr == "1") {
|
|
||||||
setBatteryPause(true, false, true); //Pause battery, do not pause CAN, equipment stop on (store to flash)
|
setBatteryPause(true, false, true); //Pause battery, do not pause CAN, equipment stop on (store to flash)
|
||||||
} else {
|
} else {
|
||||||
setBatteryPause(false, false, false);
|
setBatteryPause(false, false, false);
|
||||||
}
|
}
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
});
|
||||||
|
|
||||||
|
update_string("/equipmentStop", [](String value) {
|
||||||
|
if (value == "true" || value == "1") {
|
||||||
|
setBatteryPause(true, false, true); //Pause battery, do not pause CAN, equipment stop on (store to flash)
|
||||||
} else {
|
} else {
|
||||||
request->send(400, "text/plain", "Bad Request");
|
setBatteryPause(false, false, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing SOCMin
|
// Route for editing SOCMin
|
||||||
server.on("/updateSocMin", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateSocMin", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.min_percentage = static_cast<uint16_t>(value.toFloat() * 100);
|
datalayer.battery.settings.min_percentage = static_cast<uint16_t>(value.toFloat() * 100);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing MaxChargeA
|
// Route for editing MaxChargeA
|
||||||
server.on("/updateMaxChargeA", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateMaxChargeA", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.max_user_set_charge_dA = static_cast<uint16_t>(value.toFloat() * 10);
|
datalayer.battery.settings.max_user_set_charge_dA = static_cast<uint16_t>(value.toFloat() * 10);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing MaxDischargeA
|
// Route for editing MaxDischargeA
|
||||||
server.on("/updateMaxDischargeA", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateMaxDischargeA", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.max_user_set_discharge_dA = static_cast<uint16_t>(value.toFloat() * 10);
|
datalayer.battery.settings.max_user_set_discharge_dA = static_cast<uint16_t>(value.toFloat() * 10);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const auto& cmd : battery_commands) {
|
for (const auto& cmd : battery_commands) {
|
||||||
|
@ -649,7 +612,7 @@ void init_webserver() {
|
||||||
server.on(
|
server.on(
|
||||||
route.c_str(), HTTP_PUT,
|
route.c_str(), HTTP_PUT,
|
||||||
[cmd](AsyncWebServerRequest* request) {
|
[cmd](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password)) {
|
if (webserver_auth && !request->authenticate(http_username.c_str(), http_password.c_str())) {
|
||||||
return request->requestAuthentication();
|
return request->requestAuthentication();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -671,247 +634,88 @@ void init_webserver() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route for editing BATTERY_USE_VOLTAGE_LIMITS
|
// Route for editing BATTERY_USE_VOLTAGE_LIMITS
|
||||||
server.on("/updateUseVoltageLimit", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_int_setting("/updateUseVoltageLimit",
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](int value) { datalayer.battery.settings.user_set_voltage_limits_active = value; });
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.user_set_voltage_limits_active = value.toInt();
|
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for editing MaxChargeVoltage
|
// Route for editing MaxChargeVoltage
|
||||||
server.on("/updateMaxChargeVoltage", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateMaxChargeVoltage", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.max_user_set_charge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
datalayer.battery.settings.max_user_set_charge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing MaxDischargeVoltage
|
// Route for editing MaxDischargeVoltage
|
||||||
server.on("/updateMaxDischargeVoltage", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateMaxDischargeVoltage", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.max_user_set_discharge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
datalayer.battery.settings.max_user_set_discharge_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing FakeBatteryVoltage
|
// Route for editing FakeBatteryVoltage
|
||||||
server.on("/updateFakeBatteryVoltage", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateFakeBatteryVoltage", [](String value) { battery->set_fake_voltage(value.toFloat()); });
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (!request->hasParam("value")) {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
float val = value.toFloat();
|
|
||||||
|
|
||||||
battery->set_fake_voltage(val);
|
|
||||||
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for editing balancing enabled
|
// Route for editing balancing enabled
|
||||||
server.on("/TeslaBalAct", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_int_setting("/TeslaBalAct", [](int value) { datalayer.battery.settings.user_requests_balancing = value; });
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.user_requests_balancing = value.toInt();
|
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for editing balancing max time
|
// Route for editing balancing max time
|
||||||
server.on("/BalTime", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/BalTime", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.balancing_time_ms = static_cast<uint32_t>(value.toFloat() * 60000);
|
datalayer.battery.settings.balancing_time_ms = static_cast<uint32_t>(value.toFloat() * 60000);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing balancing max power
|
// Route for editing balancing max power
|
||||||
server.on("/BalFloatPower", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/BalFloatPower", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.balancing_float_power_W = static_cast<uint16_t>(value.toFloat());
|
datalayer.battery.settings.balancing_float_power_W = static_cast<uint16_t>(value.toFloat());
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing balancing max pack voltage
|
// Route for editing balancing max pack voltage
|
||||||
server.on("/BalMaxPackV", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/BalMaxPackV", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.balancing_max_pack_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
datalayer.battery.settings.balancing_max_pack_voltage_dV = static_cast<uint16_t>(value.toFloat() * 10);
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing balancing max cell voltage
|
// Route for editing balancing max cell voltage
|
||||||
server.on("/BalMaxCellV", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/BalMaxCellV", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.balancing_max_cell_voltage_mV = static_cast<uint16_t>(value.toFloat());
|
datalayer.battery.settings.balancing_max_cell_voltage_mV = static_cast<uint16_t>(value.toFloat());
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing balancing max cell voltage deviation
|
// Route for editing balancing max cell voltage deviation
|
||||||
server.on("/BalMaxDevCellV", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/BalMaxDevCellV", [](String value) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.battery.settings.balancing_max_deviation_cell_voltage_mV = static_cast<uint16_t>(value.toFloat());
|
datalayer.battery.settings.balancing_max_deviation_cell_voltage_mV = static_cast<uint16_t>(value.toFloat());
|
||||||
store_settings();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (charger) {
|
if (charger) {
|
||||||
// Route for editing ChargerTargetV
|
// Route for editing ChargerTargetV
|
||||||
server.on("/updateChargeSetpointV", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting(
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
"/updateChargeSetpointV", [](String value) { datalayer.charger.charger_setpoint_HV_VDC = value.toFloat(); },
|
||||||
return request->requestAuthentication();
|
[](String value) {
|
||||||
if (!request->hasParam("value")) {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
float val = value.toFloat();
|
float val = value.toFloat();
|
||||||
|
return (val <= CHARGER_MAX_HV && val >= CHARGER_MIN_HV) &&
|
||||||
if (!(val <= CHARGER_MAX_HV && val >= CHARGER_MIN_HV)) {
|
(val * datalayer.charger.charger_setpoint_HV_IDC <= CHARGER_MAX_POWER);
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(val * datalayer.charger.charger_setpoint_HV_IDC <= CHARGER_MAX_POWER)) {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
datalayer.charger.charger_setpoint_HV_VDC = val;
|
|
||||||
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing ChargerTargetA
|
// Route for editing ChargerTargetA
|
||||||
server.on("/updateChargeSetpointA", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting(
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
"/updateChargeSetpointA", [](String value) { datalayer.charger.charger_setpoint_HV_IDC = value.toFloat(); },
|
||||||
return request->requestAuthentication();
|
[](String value) {
|
||||||
if (!request->hasParam("value")) {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
float val = value.toFloat();
|
float val = value.toFloat();
|
||||||
|
return (val <= CHARGER_MAX_A) && (val <= datalayer.battery.settings.max_user_set_charge_dA) &&
|
||||||
if (!(val <= datalayer.battery.settings.max_user_set_charge_dA && val <= CHARGER_MAX_A)) {
|
(val * datalayer.charger.charger_setpoint_HV_VDC <= CHARGER_MAX_POWER);
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(val * datalayer.charger.charger_setpoint_HV_VDC <= CHARGER_MAX_POWER)) {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
|
|
||||||
datalayer.charger.charger_setpoint_HV_IDC = value.toFloat();
|
|
||||||
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route for editing ChargerEndA
|
// Route for editing ChargerEndA
|
||||||
server.on("/updateChargeEndA", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_string_setting("/updateChargeEndA",
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](String value) { datalayer.charger.charger_setpoint_HV_IDC_END = value.toFloat(); });
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.charger.charger_setpoint_HV_IDC_END = value.toFloat();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for enabling/disabling HV charger
|
// Route for enabling/disabling HV charger
|
||||||
server.on("/updateChargerHvEnabled", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_int_setting("/updateChargerHvEnabled",
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](int value) { datalayer.charger.charger_HV_enabled = (bool)value; });
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.charger.charger_HV_enabled = (bool)value.toInt();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route for enabling/disabling aux12v charger
|
// Route for enabling/disabling aux12v charger
|
||||||
server.on("/updateChargerAux12vEnabled", HTTP_GET, [](AsyncWebServerRequest* request) {
|
update_int_setting("/updateChargerAux12vEnabled",
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](int value) { datalayer.charger.charger_aux12V_enabled = (bool)value; });
|
||||||
return request->requestAuthentication();
|
|
||||||
if (request->hasParam("value")) {
|
|
||||||
String value = request->getParam("value")->value();
|
|
||||||
datalayer.charger.charger_aux12V_enabled = (bool)value.toInt();
|
|
||||||
request->send(200, "text/plain", "Updated successfully");
|
|
||||||
} else {
|
|
||||||
request->send(400, "text/plain", "Bad Request");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a GET request to <ESP_IP>/update
|
// Send a GET request to <ESP_IP>/update
|
||||||
server.on("/debug", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/debug", server, HTTP_GET,
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
[](AsyncWebServerRequest* request) { request->send(200, "text/plain", "Debug: all OK."); });
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/plain", "Debug: all OK.");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Route to handle reboot command
|
// Route to handle reboot command
|
||||||
server.on("/reboot", HTTP_GET, [](AsyncWebServerRequest* request) {
|
def_route_with_auth("/reboot", server, HTTP_GET, [](AsyncWebServerRequest* request) {
|
||||||
if (WEBSERVER_AUTH_REQUIRED && !request->authenticate(http_username, http_password))
|
|
||||||
return request->requestAuthentication();
|
|
||||||
request->send(200, "text/plain", "Rebooting server...");
|
request->send(200, "text/plain", "Rebooting server...");
|
||||||
|
|
||||||
//Equipment STOP without persisting the equipment state before restart
|
//Equipment STOP without persisting the equipment state before restart
|
||||||
|
@ -995,7 +799,7 @@ String processor(const String& var) {
|
||||||
content += "</style>";
|
content += "</style>";
|
||||||
|
|
||||||
// Compact header
|
// Compact header
|
||||||
content += "<h2>" + String(ssidAP) + "</h2>";
|
content += "<h2>" + String(ssidAP.c_str()) + "</h2>";
|
||||||
|
|
||||||
// Start content block
|
// Start content block
|
||||||
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px; border-radius: 50px'>";
|
content += "<div style='background-color: #303E47; padding: 10px; margin-bottom: 10px; border-radius: 50px'>";
|
||||||
|
@ -1551,7 +1355,7 @@ String processor(const String& var) {
|
||||||
content += "<button onclick='Cellmon()'>Cellmonitor</button> ";
|
content += "<button onclick='Cellmon()'>Cellmonitor</button> ";
|
||||||
content += "<button onclick='Events()'>Events</button> ";
|
content += "<button onclick='Events()'>Events</button> ";
|
||||||
content += "<button onclick='askReboot()'>Reboot Emulator</button>";
|
content += "<button onclick='askReboot()'>Reboot Emulator</button>";
|
||||||
if (WEBSERVER_AUTH_REQUIRED)
|
if (webserver_auth)
|
||||||
content += "<button onclick='logout()'>Logout</button>";
|
content += "<button onclick='logout()'>Logout</button>";
|
||||||
if (!datalayer.system.settings.equipment_stop_active)
|
if (!datalayer.system.settings.equipment_stop_active)
|
||||||
content +=
|
content +=
|
||||||
|
@ -1577,7 +1381,7 @@ String processor(const String& var) {
|
||||||
content += "function CANreplay() { window.location.href = '/canreplay'; }";
|
content += "function CANreplay() { window.location.href = '/canreplay'; }";
|
||||||
content += "function Log() { window.location.href = '/log'; }";
|
content += "function Log() { window.location.href = '/log'; }";
|
||||||
content += "function Events() { window.location.href = '/events'; }";
|
content += "function Events() { window.location.href = '/events'; }";
|
||||||
if (WEBSERVER_AUTH_REQUIRED) {
|
if (webserver_auth) {
|
||||||
content += "function logout() {";
|
content += "function logout() {";
|
||||||
content += " var xhr = new XMLHttpRequest();";
|
content += " var xhr = new XMLHttpRequest();";
|
||||||
content += " xhr.open('GET', '/logout', true);";
|
content += " xhr.open('GET', '/logout', true);";
|
||||||
|
@ -1589,7 +1393,7 @@ String processor(const String& var) {
|
||||||
content +=
|
content +=
|
||||||
"var xhr=new "
|
"var xhr=new "
|
||||||
"XMLHttpRequest();xhr.onload=function() { "
|
"XMLHttpRequest();xhr.onload=function() { "
|
||||||
"window.location.reload();};xhr.open('GET','/pause?p='+pause,true);xhr.send();";
|
"window.location.reload();};xhr.open('GET','/pause?value='+pause,true);xhr.send();";
|
||||||
content += "}";
|
content += "}";
|
||||||
content += "function estop(stop){";
|
content += "function estop(stop){";
|
||||||
content +=
|
content +=
|
||||||
|
|
|
@ -13,12 +13,6 @@ extern bool webserver_enabled;
|
||||||
|
|
||||||
extern const char* version_number; // The current software version, shown on webserver
|
extern const char* version_number; // The current software version, shown on webserver
|
||||||
|
|
||||||
#include <string>
|
|
||||||
extern const char* http_username;
|
|
||||||
extern const char* http_password;
|
|
||||||
|
|
||||||
extern const char* ssidAP;
|
|
||||||
|
|
||||||
// Common charger parameters
|
// Common charger parameters
|
||||||
extern float charger_stat_HVcur;
|
extern float charger_stat_HVcur;
|
||||||
extern float charger_stat_HVvol;
|
extern float charger_stat_HVvol;
|
||||||
|
|
|
@ -11,11 +11,15 @@ const bool wifi_enabled_default = false;
|
||||||
|
|
||||||
bool wifi_enabled = wifi_enabled_default;
|
bool wifi_enabled = wifi_enabled_default;
|
||||||
|
|
||||||
|
#ifdef COMMON_IMAGE
|
||||||
|
const bool wifiap_enabled_default = true;
|
||||||
|
#else
|
||||||
#ifdef WIFIAP
|
#ifdef WIFIAP
|
||||||
const bool wifiap_enabled_default = true;
|
const bool wifiap_enabled_default = true;
|
||||||
#else
|
#else
|
||||||
const bool wifiap_enabled_default = false;
|
const bool wifiap_enabled_default = false;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
bool wifiap_enabled = wifiap_enabled_default;
|
bool wifiap_enabled = wifiap_enabled_default;
|
||||||
|
|
||||||
|
@ -26,6 +30,8 @@ const bool mdns_enabled_default = false;
|
||||||
#endif
|
#endif
|
||||||
bool mdns_enabled = mdns_enabled_default;
|
bool mdns_enabled = mdns_enabled_default;
|
||||||
|
|
||||||
|
std::string ssidAP;
|
||||||
|
|
||||||
// Configuration Parameters
|
// Configuration Parameters
|
||||||
static const uint16_t WIFI_CHECK_INTERVAL = 2000; // 1 seconds normal check interval when last connected
|
static const uint16_t WIFI_CHECK_INTERVAL = 2000; // 1 seconds normal check interval when last connected
|
||||||
static const uint16_t STEP_WIFI_CHECK_INTERVAL = 2000; // 3 seconds wait step increase in checks for normal reconnects
|
static const uint16_t STEP_WIFI_CHECK_INTERVAL = 2000; // 3 seconds wait step increase in checks for normal reconnects
|
||||||
|
@ -51,12 +57,14 @@ static uint16_t current_check_interval = WIFI_CHECK_INTERVAL;
|
||||||
static bool connected_once = false;
|
static bool connected_once = false;
|
||||||
|
|
||||||
void init_WiFi() {
|
void init_WiFi() {
|
||||||
|
DEBUG_PRINTF("init_Wifi enabled=%d, apå=%d, ssid=%s, password=%s\n", wifi_enabled, wifiap_enabled, ssid.c_str(),
|
||||||
|
password.c_str());
|
||||||
|
|
||||||
if (!wifiap_enabled) {
|
if (wifiap_enabled) {
|
||||||
WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi AP and Router connection
|
WiFi.mode(WIFI_AP_STA); // Simultaneous WiFi AP and Router connection
|
||||||
init_WiFi_AP();
|
init_WiFi_AP();
|
||||||
} else {
|
} else if (wifi_enabled) {
|
||||||
WiFi.mode(WIFI_AP); // Only AP mode
|
WiFi.mode(WIFI_STA); // Only Router connection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set WiFi to auto reconnect
|
// Set WiFi to auto reconnect
|
||||||
|
@ -67,17 +75,26 @@ void init_WiFi() {
|
||||||
WiFi.config(local_IP, gateway, subnet);
|
WiFi.config(local_IP, gateway, subnet);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEBUG_PRINTF("init_Wifi set event handlers\n");
|
||||||
|
|
||||||
// Initialize Wi-Fi event handlers
|
// Initialize Wi-Fi event handlers
|
||||||
WiFi.onEvent(onWifiConnect, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);
|
WiFi.onEvent(onWifiConnect, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED);
|
||||||
WiFi.onEvent(onWifiDisconnect, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
WiFi.onEvent(onWifiDisconnect, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
|
||||||
WiFi.onEvent(onWifiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
WiFi.onEvent(onWifiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
|
||||||
|
|
||||||
// Start Wi-Fi connection
|
// Start Wi-Fi connection
|
||||||
|
DEBUG_PRINTF("start Wifi\n");
|
||||||
connectToWiFi();
|
connectToWiFi();
|
||||||
|
|
||||||
|
DEBUG_PRINTF("init_Wifi complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Task to monitor Wi-Fi status and handle reconnections
|
// Task to monitor Wi-Fi status and handle reconnections
|
||||||
void wifi_monitor() {
|
void wifi_monitor() {
|
||||||
|
if (ssid.empty() || password.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long currentMillis = millis();
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
// Check if it's time to monitor the Wi-Fi status
|
// Check if it's time to monitor the Wi-Fi status
|
||||||
|
@ -124,6 +141,11 @@ void wifi_monitor() {
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
logging.println("No previous OK connection, force a full connection attempt...");
|
logging.println("No previous OK connection, force a full connection attempt...");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
wifiap_enabled = true;
|
||||||
|
WiFi.mode(WIFI_AP_STA);
|
||||||
|
init_WiFi_AP();
|
||||||
|
|
||||||
FullReconnectToWiFi();
|
FullReconnectToWiFi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,11 +167,18 @@ void FullReconnectToWiFi() {
|
||||||
|
|
||||||
// Function to handle Wi-Fi connection
|
// Function to handle Wi-Fi connection
|
||||||
void connectToWiFi() {
|
void connectToWiFi() {
|
||||||
|
if (ssid.empty() || password.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (WiFi.status() != WL_CONNECTED) {
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
lastReconnectAttempt = millis(); // Reset the reconnect attempt timer
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
logging.println("Connecting to Wi-Fi...");
|
logging.println("Connecting to Wi-Fi...");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DEBUG_PRINTF("Connecting to Wi-Fi SSID: %s, password: %s, Channel: %d\n", ssid.c_str(), password.c_str(),
|
||||||
|
wifi_channel);
|
||||||
WiFi.begin(ssid.c_str(), password.c_str(), wifi_channel);
|
WiFi.begin(ssid.c_str(), password.c_str(), wifi_channel);
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
|
@ -163,12 +192,8 @@ void onWifiConnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
clear_event(EVENT_WIFI_DISCONNECT);
|
clear_event(EVENT_WIFI_DISCONNECT);
|
||||||
set_event(EVENT_WIFI_CONNECT, 0);
|
set_event(EVENT_WIFI_CONNECT, 0);
|
||||||
connected_once = true;
|
connected_once = true;
|
||||||
#ifdef DEBUG_LOG
|
DEBUG_PRINTF("Wi-Fi connected. RSSI: %d dBm, IP address: %s, SSID: %s\n", -WiFi.RSSI(),
|
||||||
logging.print("Wi-Fi connected. RSSI: ");
|
WiFi.localIP().toString().c_str(), WiFi.SSID().c_str());
|
||||||
logging.print(-WiFi.RSSI());
|
|
||||||
logging.print(" dBm, IP address: ");
|
|
||||||
logging.println(WiFi.localIP().toString());
|
|
||||||
#endif
|
|
||||||
hasConnectedBefore = true; // Mark as successfully connected at least once
|
hasConnectedBefore = true; // Mark as successfully connected at least once
|
||||||
reconnectAttempts = 0; // Reset the attempt counter
|
reconnectAttempts = 0; // Reset the attempt counter
|
||||||
current_full_reconnect_interval = INIT_WIFI_FULL_RECONNECT_INTERVAL; // Reset the full reconnect interval
|
current_full_reconnect_interval = INIT_WIFI_FULL_RECONNECT_INTERVAL; // Reset the full reconnect interval
|
||||||
|
@ -189,8 +214,10 @@ void onWifiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
|
|
||||||
// Event handler for Wi-Fi disconnection
|
// Event handler for Wi-Fi disconnection
|
||||||
void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
void onWifiDisconnect(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
if (connected_once)
|
|
||||||
|
if (connected_once) {
|
||||||
set_event(EVENT_WIFI_DISCONNECT, 0);
|
set_event(EVENT_WIFI_DISCONNECT, 0);
|
||||||
|
}
|
||||||
#ifdef DEBUG_LOG
|
#ifdef DEBUG_LOG
|
||||||
logging.println("Wi-Fi disconnected.");
|
logging.println("Wi-Fi disconnected.");
|
||||||
#endif
|
#endif
|
||||||
|
@ -218,15 +245,13 @@ void init_mDNS() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_WiFi_AP() {
|
void init_WiFi_AP() {
|
||||||
#ifdef DEBUG_LOG
|
ssidAP = std::string("BatteryEmulator") + WiFi.macAddress().c_str();
|
||||||
logging.println("Creating Access Point: " + String(ssidAP));
|
|
||||||
logging.println("With password: " + String(passwordAP));
|
DEBUG_PRINTF("Creating Access Point: %s\n", ssidAP.c_str());
|
||||||
#endif
|
DEBUG_PRINTF("With password: %s\n", passwordAP.c_str());
|
||||||
WiFi.softAP(ssidAP, passwordAP);
|
|
||||||
|
WiFi.softAP(ssidAP.c_str(), passwordAP.c_str());
|
||||||
IPAddress IP = WiFi.softAPIP();
|
IPAddress IP = WiFi.softAPIP();
|
||||||
#ifdef DEBUG_LOG
|
|
||||||
logging.println("Access Point created.");
|
DEBUG_PRINTF("Access Point created.\nIP address: %s\n", IP.toString().c_str());
|
||||||
logging.print("IP address: ");
|
|
||||||
logging.println(IP.toString());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
extern std::string ssid;
|
extern std::string ssid;
|
||||||
extern std::string password;
|
extern std::string password;
|
||||||
extern const uint8_t wifi_channel;
|
extern const uint8_t wifi_channel;
|
||||||
extern const char* ssidAP;
|
extern std::string ssidAP;
|
||||||
extern const char* passwordAP;
|
extern std::string passwordAP;
|
||||||
|
|
||||||
void init_WiFi();
|
void init_WiFi();
|
||||||
void wifi_monitor();
|
void wifi_monitor();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue