2024-04-13 18:20:10 +02:00
|
|
|
#include <ArduinoJson.h>
|
2024-02-25 16:00:44 +01:00
|
|
|
#include "configuration.h"
|
2024-02-24 14:09:05 +01:00
|
|
|
#include "ota_utils.h"
|
|
|
|
|
#include "web_utils.h"
|
2024-05-24 20:24:40 +02:00
|
|
|
#include "display.h"
|
2024-04-13 18:20:10 +02:00
|
|
|
#include "utils.h"
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-04-13 18:20:10 +02:00
|
|
|
extern Configuration Config;
|
|
|
|
|
extern uint32_t lastBeaconTx;
|
|
|
|
|
extern std::vector<ReceivedPacket> receivedPackets;
|
2024-02-24 14:09:05 +01:00
|
|
|
|
|
|
|
|
extern const char web_index_html[] asm("_binary_data_embed_index_html_gz_start");
|
|
|
|
|
extern const char web_index_html_end[] asm("_binary_data_embed_index_html_gz_end");
|
|
|
|
|
extern const size_t web_index_html_len = web_index_html_end - web_index_html;
|
|
|
|
|
|
|
|
|
|
extern const char web_style_css[] asm("_binary_data_embed_style_css_gz_start");
|
|
|
|
|
extern const char web_style_css_end[] asm("_binary_data_embed_style_css_gz_end");
|
|
|
|
|
extern const size_t web_style_css_len = web_style_css_end - web_style_css;
|
|
|
|
|
|
|
|
|
|
extern const char web_script_js[] asm("_binary_data_embed_script_js_gz_start");
|
|
|
|
|
extern const char web_script_js_end[] asm("_binary_data_embed_script_js_gz_end");
|
|
|
|
|
extern const size_t web_script_js_len = web_script_js_end - web_script_js;
|
|
|
|
|
|
|
|
|
|
extern const char web_bootstrap_css[] asm("_binary_data_embed_bootstrap_css_gz_start");
|
|
|
|
|
extern const char web_bootstrap_css_end[] asm("_binary_data_embed_bootstrap_css_gz_end");
|
|
|
|
|
extern const size_t web_bootstrap_css_len = web_bootstrap_css_end - web_bootstrap_css;
|
|
|
|
|
|
|
|
|
|
extern const char web_bootstrap_js[] asm("_binary_data_embed_bootstrap_js_gz_start");
|
|
|
|
|
extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end");
|
|
|
|
|
extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js;
|
|
|
|
|
|
2024-07-09 05:29:04 +02:00
|
|
|
// Declare external symbols for the embedded image data
|
|
|
|
|
extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz_start");
|
|
|
|
|
extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end");
|
|
|
|
|
extern const size_t favicon_data_len = favicon_data_end - favicon_data;
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
namespace WEB_Utils {
|
|
|
|
|
|
|
|
|
|
AsyncWebServer server(80);
|
|
|
|
|
|
|
|
|
|
void handleNotFound(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse(404, "text/plain", "Not found");
|
|
|
|
|
response->addHeader("Cache-Control", "max-age=3600");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleStatus(AsyncWebServerRequest *request) {
|
|
|
|
|
request->send(200, "text/plain", "OK");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleHome(AsyncWebServerRequest *request) {
|
2024-08-13 20:48:08 +02:00
|
|
|
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
|
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", (const uint8_t*)web_index_html, web_index_html_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 05:29:04 +02:00
|
|
|
void handleFavicon(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "image/x-icon", (const uint8_t*)favicon_data, favicon_data_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
void handleReadConfiguration(AsyncWebServerRequest *request) {
|
2024-08-13 20:48:08 +02:00
|
|
|
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
|
|
|
|
|
return request->requestAuthentication();
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
File file = SPIFFS.open("/igate_conf.json");
|
|
|
|
|
|
|
|
|
|
String fileContent;
|
|
|
|
|
while(file.available()){
|
|
|
|
|
fileContent += String((char)file.read());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
request->send(200, "application/json", fileContent);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-13 18:20:10 +02:00
|
|
|
void handleReceivedPackets(AsyncWebServerRequest *request) {
|
|
|
|
|
StaticJsonDocument<1536> data;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < receivedPackets.size(); i++) {
|
|
|
|
|
data[i]["millis"] = receivedPackets[i].millis;
|
|
|
|
|
data[i]["packet"] = receivedPackets[i].packet;
|
|
|
|
|
data[i]["RSSI"] = receivedPackets[i].RSSI;
|
|
|
|
|
data[i]["SNR"] = receivedPackets[i].SNR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String buffer;
|
|
|
|
|
|
|
|
|
|
serializeJson(data, buffer);
|
|
|
|
|
|
|
|
|
|
request->send(200, "application/json", buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
void handleWriteConfiguration(AsyncWebServerRequest *request) {
|
|
|
|
|
Serial.println("Got new config from www");
|
|
|
|
|
|
|
|
|
|
int networks = request->getParam("wifi.APs", true)->value().toInt();
|
|
|
|
|
|
|
|
|
|
Config.wifiAPs = {};
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<networks; i++) {
|
|
|
|
|
WiFi_AP wifiap;
|
|
|
|
|
wifiap.ssid = request->getParam("wifi.AP." + String(i) + ".ssid", true)->value();
|
|
|
|
|
wifiap.password = request->getParam("wifi.AP." + String(i) + ".password", true)->value();
|
|
|
|
|
|
|
|
|
|
Config.wifiAPs.push_back(wifiap);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.callsign = request->getParam("callsign", true)->value();
|
2024-05-24 01:27:10 +02:00
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value();
|
|
|
|
|
Config.wifiAutoAP.powerOff = request->getParam("wifi.autoAP.powerOff", true)->value().toInt();
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.aprs_is.active = request->hasParam("aprs_is.active", true);
|
|
|
|
|
Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value();
|
|
|
|
|
Config.aprs_is.server = request->getParam("aprs_is.server", true)->value();
|
|
|
|
|
Config.aprs_is.port = request->getParam("aprs_is.port", true)->value().toInt();
|
|
|
|
|
Config.aprs_is.filter = request->getParam("aprs_is.filter", true)->value();
|
|
|
|
|
Config.aprs_is.messagesToRF = request->hasParam("aprs_is.messagesToRF", true);
|
|
|
|
|
Config.aprs_is.objectsToRF = request->hasParam("aprs_is.objectsToRF", true);
|
2024-05-24 01:27:10 +02:00
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.beacon.interval = request->getParam("beacon.interval", true)->value().toInt();
|
|
|
|
|
Config.beacon.sendViaAPRSIS = request->hasParam("beacon.sendViaAPRSIS", true);
|
|
|
|
|
Config.beacon.sendViaRF = request->hasParam("beacon.sendViaRF", true);
|
|
|
|
|
Config.beacon.latitude = request->getParam("beacon.latitude", true)->value().toDouble();
|
|
|
|
|
Config.beacon.longitude = request->getParam("beacon.longitude", true)->value().toDouble();
|
|
|
|
|
Config.beacon.comment = request->getParam("beacon.comment", true)->value();
|
|
|
|
|
Config.beacon.overlay = request->getParam("beacon.overlay", true)->value();
|
|
|
|
|
Config.beacon.symbol = request->getParam("beacon.symbol", true)->value();
|
|
|
|
|
Config.beacon.path = request->getParam("beacon.path", true)->value();
|
|
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.digi.mode = request->getParam("digi.mode", true)->value().toInt();
|
2024-03-07 17:46:38 +01:00
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.loramodule.txFreq = request->getParam("lora.txFreq", true)->value().toInt();
|
|
|
|
|
Config.loramodule.rxFreq = request->getParam("lora.rxFreq", true)->value().toInt();
|
|
|
|
|
Config.loramodule.spreadingFactor = request->getParam("lora.spreadingFactor", true)->value().toInt();
|
|
|
|
|
Config.loramodule.signalBandwidth = request->getParam("lora.signalBandwidth", true)->value().toInt();
|
|
|
|
|
Config.loramodule.codingRate4 = request->getParam("lora.codingRate4", true)->value().toInt();
|
|
|
|
|
Config.loramodule.power = request->getParam("lora.power", true)->value().toInt();
|
|
|
|
|
Config.loramodule.txActive = request->hasParam("lora.txActive", true);
|
|
|
|
|
Config.loramodule.rxActive = request->hasParam("lora.rxActive", true);
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.display.alwaysOn = request->hasParam("display.alwaysOn", true);
|
2024-02-24 14:09:05 +01:00
|
|
|
if (!Config.display.alwaysOn) {
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.display.timeout = request->getParam("display.timeout", true)->value().toInt();
|
2024-02-24 14:09:05 +01:00
|
|
|
}
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.display.turn180 = request->hasParam("display.turn180", true);
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-05-24 17:48:12 +02:00
|
|
|
|
|
|
|
|
Config.battery.sendInternalVoltage = request->hasParam("battery.sendInternalVoltage", true);
|
|
|
|
|
Config.battery.monitorInternalVoltage = request->hasParam("battery.monitorInternalVoltage", true);
|
2024-06-27 00:13:02 +02:00
|
|
|
Config.battery.internalSleepVoltage = request->getParam("battery.internalSleepVoltage", true)->value().toFloat();
|
2024-05-24 17:48:12 +02:00
|
|
|
|
|
|
|
|
Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true);
|
|
|
|
|
if (Config.battery.sendExternalVoltage) {
|
|
|
|
|
Config.battery.externalVoltagePin = request->getParam("battery.externalVoltagePin", true)->value().toInt();
|
2024-06-27 00:13:02 +02:00
|
|
|
Config.battery.voltageDividerR1 = request->getParam("battery.voltageDividerR1", true)->value().toFloat();
|
|
|
|
|
Config.battery.voltageDividerR2 = request->getParam("battery.voltageDividerR2", true)->value().toFloat();
|
2024-05-24 17:48:12 +02:00
|
|
|
}
|
|
|
|
|
Config.battery.monitorExternalVoltage = request->hasParam("battery.monitorExternalVoltage", true);
|
2024-06-27 00:13:02 +02:00
|
|
|
Config.battery.externalSleepVoltage = request->getParam("battery.externalSleepVoltage", true)->value().toFloat();
|
|
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.bme.active = request->hasParam("bme.active", true);
|
|
|
|
|
Config.bme.heightCorrection = request->getParam("bme.heightCorrection", true)->value().toInt();
|
|
|
|
|
Config.bme.temperatureCorrection = request->getParam("bme.temperatureCorrection", true)->value().toFloat();
|
|
|
|
|
if (Config.bme.active) {
|
|
|
|
|
Config.beacon.symbol = "_";
|
|
|
|
|
}
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.syslog.active = request->hasParam("syslog.active", true);
|
2024-02-24 14:09:05 +01:00
|
|
|
if (Config.syslog.active) {
|
2024-06-27 00:13:02 +02:00
|
|
|
Config.syslog.server = request->getParam("syslog.server", true)->value();
|
|
|
|
|
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
|
2024-02-24 14:09:05 +01:00
|
|
|
}
|
2024-05-24 01:27:10 +02:00
|
|
|
|
2024-06-27 00:13:02 +02:00
|
|
|
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
|
|
|
|
|
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
|
|
|
|
|
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.rebootMode = request->hasParam("other.rebootMode", true);
|
|
|
|
|
Config.rebootModeTime = request->getParam("other.rebootModeTime", true)->value().toInt();
|
2024-05-24 17:48:12 +02:00
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.ota.username = request->getParam("ota.username", true)->value();
|
|
|
|
|
Config.ota.password = request->getParam("ota.password", true)->value();
|
2024-02-24 14:09:05 +01:00
|
|
|
|
2024-06-26 19:05:45 +02:00
|
|
|
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt();
|
2024-05-24 16:43:06 +02:00
|
|
|
|
2024-05-24 01:27:10 +02:00
|
|
|
Config.backupDigiMode = request->hasParam("other.backupDigiMode", true);
|
2024-05-21 03:54:55 +02:00
|
|
|
Config.lowPowerMode = request->hasParam("other.lowPowerMode", true);
|
|
|
|
|
Config.lowVoltageCutOff = request->getParam("other.lowVoltageCutOff", true)->value().toDouble();
|
2024-03-28 18:00:46 +01:00
|
|
|
|
2024-06-26 19:05:45 +02:00
|
|
|
Config.personalNote = request->getParam("personalNote", true)->value();
|
|
|
|
|
|
2024-08-13 20:48:08 +02:00
|
|
|
Config.webadmin.active = request->hasParam("webadmin.active", true);
|
|
|
|
|
if (Config.webadmin.active) {
|
|
|
|
|
Config.webadmin.username = request->getParam("webadmin.username", true)->value();
|
|
|
|
|
Config.webadmin.password = request->getParam("webadmin.password", true)->value();
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
Config.writeFile();
|
|
|
|
|
|
2024-05-21 03:54:55 +02:00
|
|
|
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
|
2024-02-24 14:09:05 +01:00
|
|
|
response->addHeader("Location", "/");
|
|
|
|
|
request->send(response);
|
2024-08-14 18:32:34 +02:00
|
|
|
displayToggle(false);
|
2024-02-24 14:09:05 +01:00
|
|
|
ESP.restart();
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-19 17:02:42 +01:00
|
|
|
void handleAction(AsyncWebServerRequest *request) {
|
|
|
|
|
String type = request->getParam("type", false)->value();
|
|
|
|
|
|
|
|
|
|
if (type == "send-beacon") {
|
|
|
|
|
lastBeaconTx = 0;
|
|
|
|
|
|
|
|
|
|
request->send(200, "text/plain", "Beacon will be sent in a while");
|
|
|
|
|
} else if (type == "reboot") {
|
2024-08-14 18:32:34 +02:00
|
|
|
displayToggle(false);
|
2024-03-19 17:02:42 +01:00
|
|
|
ESP.restart();
|
|
|
|
|
} else {
|
|
|
|
|
request->send(404, "text/plain", "Not Found");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 14:09:05 +01:00
|
|
|
void handleStyle(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_style_css, web_style_css_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleScript(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_script_js, web_script_js_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleBootstrapStyle(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_bootstrap_css, web_bootstrap_css_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
response->addHeader("Cache-Control", "max-age=3600");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleBootstrapScript(AsyncWebServerRequest *request) {
|
|
|
|
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_bootstrap_js, web_bootstrap_js_len);
|
|
|
|
|
response->addHeader("Content-Encoding", "gzip");
|
|
|
|
|
response->addHeader("Cache-Control", "max-age=3600");
|
|
|
|
|
request->send(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
|
server.on("/", HTTP_GET, handleHome);
|
|
|
|
|
server.on("/status", HTTP_GET, handleStatus);
|
2024-04-13 18:20:10 +02:00
|
|
|
server.on("/received-packets.json", HTTP_GET, handleReceivedPackets);
|
2024-02-24 14:09:05 +01:00
|
|
|
server.on("/configuration.json", HTTP_GET, handleReadConfiguration);
|
|
|
|
|
server.on("/configuration.json", HTTP_POST, handleWriteConfiguration);
|
2024-03-19 17:02:42 +01:00
|
|
|
server.on("/action", HTTP_POST, handleAction);
|
2024-02-24 14:09:05 +01:00
|
|
|
server.on("/style.css", HTTP_GET, handleStyle);
|
|
|
|
|
server.on("/script.js", HTTP_GET, handleScript);
|
|
|
|
|
server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle);
|
|
|
|
|
server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript);
|
2024-07-09 05:29:04 +02:00
|
|
|
server.on("/favicon.png", HTTP_GET, handleFavicon);
|
2024-02-24 14:09:05 +01:00
|
|
|
|
|
|
|
|
OTA_Utils::setup(&server); // Include OTA Updater for WebServer
|
|
|
|
|
|
|
|
|
|
server.onNotFound(handleNotFound);
|
|
|
|
|
|
|
|
|
|
server.begin();
|
|
|
|
|
}
|
2024-02-25 16:00:44 +01:00
|
|
|
|
|
|
|
|
}
|