299 lines
8.9 KiB
C++
299 lines
8.9 KiB
C++
#include <ESPMegaWebServer.hpp>
|
|
|
|
ESPMegaWebServer::ESPMegaWebServer(uint16_t port, ESPMegaIoT *iot)
|
|
{
|
|
this->port = port;
|
|
this->iot = iot;
|
|
this->server = new AsyncWebServer(port);
|
|
}
|
|
|
|
ESPMegaWebServer::~ESPMegaWebServer()
|
|
{
|
|
delete this->server;
|
|
}
|
|
|
|
void ESPMegaWebServer::begin()
|
|
{
|
|
this->loadCredentialsFromFRAM();
|
|
this->server->begin();
|
|
auto bindedDashboardHandler = std::bind(&ESPMegaWebServer::dashboardHandler, this, std::placeholders::_1);
|
|
this->server->on("/", HTTP_GET, bindedDashboardHandler);
|
|
auto bindedConfigHandler = std::bind(&ESPMegaWebServer::configHandler, this, std::placeholders::_1);
|
|
this->server->on("/config", HTTP_GET, bindedConfigHandler);
|
|
auto bindedSaveConfigHandler = std::bind(&ESPMegaWebServer::saveConfigHandler, this, std::placeholders::_1);
|
|
this->server->on("/config", HTTP_POST, bindedSaveConfigHandler);
|
|
}
|
|
|
|
void ESPMegaWebServer::loop()
|
|
{
|
|
// AsyncWebServer doesn't have a loop function
|
|
}
|
|
|
|
void ESPMegaWebServer::bindFRAM(FRAM *fram)
|
|
{
|
|
this->fram = fram;
|
|
}
|
|
|
|
void ESPMegaWebServer::loadCredentialsFromFRAM()
|
|
{
|
|
this->fram->read(301, (uint8_t*)this->webUsername, 32);
|
|
this->fram->read(333, (uint8_t*)this->webPassword, 32);
|
|
// Verify if credentials are valid
|
|
// A valid username and password is null terminated
|
|
// Scan for null terminator
|
|
bool validUsername = false;
|
|
bool validPassword = false;
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
if (this->webUsername[i] == '\0')
|
|
{
|
|
validUsername = true;
|
|
break;
|
|
}
|
|
}
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
if (this->webPassword[i] == '\0')
|
|
{
|
|
validPassword = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!validUsername || !validPassword)
|
|
{
|
|
this->resetCredentials();
|
|
return;
|
|
}
|
|
// A valid username and password is at least 1 character long
|
|
if(strlen(this->webUsername) == 0 || strlen(this->webPassword) == 0)
|
|
{
|
|
this->resetCredentials();
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ESPMegaWebServer::saveCredentialsToFRAM()
|
|
{
|
|
this->fram->write(301, (uint8_t*)this->webUsername, 32);
|
|
this->fram->write(333, (uint8_t*)this->webPassword, 32);
|
|
}
|
|
|
|
void ESPMegaWebServer::resetCredentials()
|
|
{
|
|
// The default username and password is "admin"
|
|
strcpy(this->webUsername, "admin");
|
|
strcpy(this->webPassword, "admin");
|
|
this->saveCredentialsToFRAM();
|
|
}
|
|
|
|
char* ESPMegaWebServer::getWebUsername()
|
|
{
|
|
return this->webUsername;
|
|
}
|
|
|
|
char* ESPMegaWebServer::getWebPassword()
|
|
{
|
|
return this->webPassword;
|
|
}
|
|
|
|
void ESPMegaWebServer::setWebUsername(const char* username)
|
|
{
|
|
strcpy(this->webUsername, username);
|
|
}
|
|
|
|
void ESPMegaWebServer::setWebPassword(const char* password)
|
|
{
|
|
strcpy(this->webPassword, password);
|
|
}
|
|
|
|
void ESPMegaWebServer::dashboardHandler(AsyncWebServerRequest *request)
|
|
{
|
|
request->authenticate(this->webUsername, this->webPassword);
|
|
auto bindedDashboardProcessor = std::bind(&ESPMegaWebServer::dashboardProcessor, this, std::placeholders::_1);
|
|
request->send_P(200, "text/html", ota_html, bindedDashboardProcessor);
|
|
|
|
}
|
|
|
|
String ESPMegaWebServer::dashboardProcessor(const String &var)
|
|
{
|
|
if (var == "hostname")
|
|
{
|
|
return String(this->iot->getNetworkConfig()->hostname);
|
|
}
|
|
else if (var == "ip_address")
|
|
{
|
|
return this->iot->getIp().toString();
|
|
}
|
|
else if (var == "mac_address")
|
|
{
|
|
return this->iot->getMac();
|
|
}
|
|
else if (var == "model")
|
|
{
|
|
return String("ESPMega PRO R3.3c");
|
|
}
|
|
else if (var == "mqtt_connection_string")
|
|
{
|
|
MqttConfig *mqttConfig = this->iot->getMqttConfig();
|
|
String connectionString;
|
|
connectionString += mqttConfig->mqtt_server;
|
|
connectionString += ":";
|
|
connectionString += mqttConfig->mqtt_port;
|
|
return connectionString;
|
|
}
|
|
else if (var == "base_topic")
|
|
{
|
|
return String(this->iot->getMqttConfig()->base_topic);
|
|
}
|
|
else if (var == "mqtt_connected")
|
|
{
|
|
return this->iot->mqttConnected() ? "Connected" : "Standalone";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
void ESPMegaWebServer::configHandler(AsyncWebServerRequest *request)
|
|
{
|
|
request->authenticate(this->webUsername, this->webPassword);
|
|
auto bindedConfigProcessor = std::bind(&ESPMegaWebServer::configProcessor, this, std::placeholders::_1);
|
|
request->send_P(200, "text/html", config_html, bindedConfigProcessor);
|
|
}
|
|
|
|
String ESPMegaWebServer::configProcessor(const String &var)
|
|
{
|
|
MqttConfig *mqttConfig = this->iot->getMqttConfig();
|
|
NetworkConfig *networkConfig = this->iot->getNetworkConfig();
|
|
if (var == "ip_address")
|
|
{
|
|
return networkConfig->ip.toString();
|
|
}
|
|
else if (var == "netmask")
|
|
{
|
|
return networkConfig->subnet.toString();
|
|
}
|
|
else if (var == "gateway")
|
|
{
|
|
return networkConfig->gateway.toString();
|
|
}
|
|
else if (var == "dns")
|
|
{
|
|
return networkConfig->dns1.toString();
|
|
}
|
|
else if (var == "hostname")
|
|
{
|
|
return String(networkConfig->hostname);
|
|
}
|
|
else if (var == "bms_ip")
|
|
{
|
|
return String(mqttConfig->mqtt_server);
|
|
}
|
|
else if (var == "bms_port")
|
|
{
|
|
return String(mqttConfig->mqtt_port);
|
|
}
|
|
else if (var == "bms_useauth") {
|
|
return mqttConfig->mqtt_useauth ? "checked=\"checked\"" : "";
|
|
}
|
|
else if (var == "bms_username")
|
|
{
|
|
return String(mqttConfig->mqtt_user);
|
|
}
|
|
else if (var == "bms_password")
|
|
{
|
|
return String(mqttConfig->mqtt_password);
|
|
}
|
|
else if (var == "bms_endpoint")
|
|
{
|
|
return String(mqttConfig->base_topic);
|
|
}
|
|
else if (var == "web_username")
|
|
{
|
|
return String(this->webUsername);
|
|
}
|
|
else if (var == "web_password")
|
|
{
|
|
return String(this->webPassword);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
void ESPMegaWebServer::otaHandler(AsyncWebServerRequest *request)
|
|
{
|
|
// Prepare to receive firmware
|
|
|
|
}
|
|
|
|
void ESPMegaWebServer::saveConfigHandler(AsyncWebServerRequest *request) {
|
|
/**
|
|
* Request POST body should be a JSON object
|
|
* containing the following fields:
|
|
* ip_address: String, the IP address of the device
|
|
* netmask: String, the netmask of the device
|
|
* gateway: String, the gateway of the device
|
|
* dns: String, the DNS of the device
|
|
* hostname: String, the hostname of the device
|
|
* bms_ip: String, the IP address of the MQTT broker
|
|
* bms_port: int, the port of the MQTT broker
|
|
* bms_useauth: Boolean, true if the MQTT broker requires authentication
|
|
* bms_username: String, the username of the MQTT broker
|
|
* bms_password: String, the password of the MQTT broker
|
|
* bms_endpoint: String, the base topic of the MQTT broker
|
|
* web_username: String, the username of the web server
|
|
* web_password: String, the password of the web server
|
|
*/
|
|
StaticJsonDocument<1024> doc;
|
|
DeserializationError error = deserializeJson(doc, request->getParam("plain")->value());
|
|
if (error) {
|
|
request->send(400, "text/plain", "Invalid JSON");
|
|
return;
|
|
}
|
|
JsonObject root = doc.as<JsonObject>();
|
|
// Network Config
|
|
NetworkConfig networkConfig;
|
|
IPAddress ip;
|
|
if (!ip.fromString(root["ip_address"].as<String>())) {
|
|
request->send(400, "text/plain", "Invalid IP Address");
|
|
return;
|
|
}
|
|
networkConfig.ip = ip;
|
|
if (!ip.fromString(root["netmask"].as<String>())) {
|
|
request->send(400, "text/plain", "Invalid Netmask");
|
|
return;
|
|
}
|
|
networkConfig.subnet = ip;
|
|
if (!ip.fromString(root["gateway"].as<String>())) {
|
|
request->send(400, "text/plain", "Invalid Gateway");
|
|
return;
|
|
}
|
|
networkConfig.gateway = ip;
|
|
if (!ip.fromString(root["dns"].as<String>())) {
|
|
request->send(400, "text/plain", "Invalid DNS");
|
|
return;
|
|
}
|
|
networkConfig.dns1 = ip;
|
|
strcpy(networkConfig.hostname, root["hostname"].as<String>().c_str());
|
|
// MQTT Config
|
|
MqttConfig mqttConfig;
|
|
strcpy(mqttConfig.mqtt_server, root["bms_ip"].as<String>().c_str());
|
|
uint16_t mqttPort = root["bms_port"].as<int>();
|
|
if (mqttConfig.mqtt_port <= 0 || mqttConfig.mqtt_port > 65535) {
|
|
request->send(400, "text/plain", "Invalid MQTT Port");
|
|
return;
|
|
}
|
|
mqttConfig.mqtt_port = mqttPort;
|
|
mqttConfig.mqtt_useauth = root["bms_useauth"].as<bool>();
|
|
strcpy(mqttConfig.mqtt_user, root["bms_username"].as<String>().c_str());
|
|
strcpy(mqttConfig.mqtt_password, root["bms_password"].as<String>().c_str());
|
|
strcpy(mqttConfig.base_topic, root["bms_endpoint"].as<String>().c_str());
|
|
// Web Server Config
|
|
strcpy(this->webUsername, root["web_username"].as<String>().c_str());
|
|
strcpy(this->webPassword, root["web_password"].as<String>().c_str());
|
|
// Commit changes to FRAM
|
|
this->iot->setNetworkConfig(networkConfig);
|
|
this->iot->saveNetworkConfig();
|
|
this->iot->setMqttConfig(mqttConfig);
|
|
this->iot->saveMqttConfig();
|
|
this->saveCredentialsToFRAM();
|
|
// Send response
|
|
request->send(200, "text/plain", "OK");
|
|
} |