#include "WebServer.h" #include "DebugLog.h" #include "DataLogger.h" #include #include #include #include "HTTPServer.hpp" #include "SSLCert.hpp" #include "HTTPRequest.hpp" #include "HTTPResponse.hpp" /** Check if we have multiple cores */ #if CONFIG_FREERTOS_UNICORE #define WEBSERVER_RUNNING_CORE 0 #else #define WEBSERVER_RUNNING_CORE 1 #endif using namespace httpsserver; detail::WebServer WebServer; namespace detail { HTTPServer httpServer; WebServer::WebServer() { } WebServer::~WebServer() { } void WebServer::begin() { ::DebugLog.println("Creating server task... "); xTaskCreatePinnedToCore(WebServer::ServerTask_, "webserver", 6144, nullptr, 1, nullptr, WEBSERVER_RUNNING_CORE); } void WebServer::setStatus(const Status& status) { status_ = status; } void WebServer::ServerTask_(void* params) { // Main HTML page ResourceNode* nodeRoot = new ResourceNode("/", "GET", &WebServer::HandleIndex_); ResourceNode* nodeIndex = new ResourceNode("/index.html", "GET", &WebServer::HandleIndex_); httpServer.registerNode(nodeRoot); httpServer.registerNode(nodeIndex); // API ResourceNode* nodeGetStatus = new ResourceNode("/api/status", "GET", &WebServer::HandleGetStatus_); ResourceNode* nodePostInfo = new ResourceNode("/api/info", "POST", &WebServer::HandlePostInfo_); httpServer.registerNode(nodeGetStatus); httpServer.registerNode(nodePostInfo); // Default node (either a static file, if found, or a 404 error) ResourceNode* nodeDefault = new ResourceNode("", "GET", &WebServer::HandleDefault_); httpServer.setDefaultNode(nodeDefault); ::DebugLog.println("Starting server... "); httpServer.start(); if (httpServer.isRunning()) { ::DebugLog.println("Server ready."); while(true) { httpServer.loop(); delay(1); } } } void WebServer::HandleIndex_(HTTPRequest * request, HTTPResponse * response) { // Status code is 200 OK by default. response->setHeader("Content-Type", "text/html"); File file = SPIFFS.open("/www/index.html"); SendContent_(file, response); file.close(); } void WebServer::HandleGetStatus_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response) { const Status& status = ::WebServer.status_; int v = status.batteryVoltage; int c = status.batteryOutputCurrent; int s = (int)(status.speed * 1000.0f + 0.5f); int temp = status.temperature; int alt = status.altitude; int td = status.tripDistance; int ttt = status.tripTotalTime; int tmt = status.tripMovingTime; int tae = status.tripAscendingElevation / 100; // convert mm to dm int tme = status.tripMotorEnergy / 360; // convert Joules to dWh (tenth of Wh) float latitude = -1000.0f; float longitude = -1000.0f; char realtime[64] = {0}; const char* logFileName = DataLogger::get().currentLogFileName(); if(String(logFileName).startsWith("/log/")) logFileName += 5; int totalSize = (int)(SPIFFS.totalBytes() / 1000); int usedSize = (int)(SPIFFS.usedBytes() / 1000); char json[256]; sprintf(json, "{\"v\":%d,\"c\":%d,\"s\":%d,\"td\":%d,\"ttt\":%d,\"tmt\":%d,\"tae\":%d,\"tme\":%d,\"temp\":%d,\"alt\":%d,\"log\":\"%s\",\"tot\":%d,\"used\":%d,\"lat\":%.5f,\"lng\":%.5f,\"d\":\"%s\"}", v, c, s, td, ttt, tmt, tae, tme, temp, alt, logFileName, totalSize, usedSize, latitude, longitude, realtime); response->setHeader("Content-Type", "text/json"); response->print(json); } void WebServer::HandlePostInfo_(httpsserver::HTTPRequest * request, httpsserver::HTTPResponse * response) { request->discardRequestBody(); } void WebServer::HandleDefault_(HTTPRequest * request, HTTPResponse * response) { // Discard request body, if we received any // We do this, as this is the default node and may also server POST/PUT requests request->discardRequestBody(); std::string filePath = "/www"; std::string fullURL = request->getRequestString(); filePath = filePath + fullURL.substr(0, fullURL.find("?")); //::DebugLog.println(filePath.c_str()); File file = SPIFFS.open(filePath.c_str()); if(!file || file.isDirectory()) { // We've not found any matching file, so this is a 404 error response->setStatusCode(404); response->setStatusText("Not Found"); response->setHeader("Content-Type", "text/html"); response->println(""); response->println(""); response->println("Not Found"); response->println("

404 Not Found

The requested resource was not found on this server.

"); response->println(""); } else { // We've found a file, send the content response->setHeader("Cache-Control", "max-age=5184000"); SendContent_(file, response); } file.close(); } void WebServer::SendContent_(Stream& stream, httpsserver::HTTPResponse * response) { uint8_t buffer[512]; while(stream.available()) { size_t numBytes = stream.readBytes(buffer, sizeof(buffer)); response->write(buffer, numBytes); } } }