diff --git a/interface/progmem-generator.js b/interface/progmem-generator.js index e68e047b6..c50c565d1 100644 --- a/interface/progmem-generator.js +++ b/interface/progmem-generator.js @@ -2,6 +2,7 @@ import { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } import { resolve, relative, sep } from 'path'; import zlib from 'zlib'; import mime from 'mime-types'; +import crypto from 'crypto'; const ARDUINO_INCLUDES = '#include \n\n'; const INDENT = ' '; @@ -11,14 +12,17 @@ const bytesPerLine = 20; var totalSize = 0; const generateWWWClass = () => - `typedef std::function RouteRegistrationHandler; + `typedef std::function RouteRegistrationHandler; // Total size is ${totalSize} bytes class WWWData { ${indent}public: ${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) { ${fileInfo - .map((file) => `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size});`) + .map( + (file) => + `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size}, "${file.hash}");` + ) .join('\n')} ${indent.repeat(2)}} }; @@ -50,6 +54,12 @@ const writeFile = (relativeFilePath, buffer) => { writeStream.write('const uint8_t ' + variable + '[] = {'); // const zipBuffer = zlib.brotliCompressSync(buffer, { quality: 1 }); const zipBuffer = zlib.gzipSync(buffer, { level: 9 }); + + // create sha + const hashSum = crypto.createHash('sha256'); + hashSum.update(zipBuffer); + const hash = hashSum.digest('hex'); + zipBuffer.forEach((b) => { if (!(size % bytesPerLine)) { writeStream.write('\n'); @@ -58,15 +68,19 @@ const writeFile = (relativeFilePath, buffer) => { writeStream.write('0x' + ('00' + b.toString(16).toUpperCase()).slice(-2) + ','); size++; }); + if (size % bytesPerLine) { writeStream.write('\n'); } + writeStream.write('};\n\n'); + fileInfo.push({ uri: '/' + relativeFilePath.replace(sep, '/'), mimeType, variable, - size + size, + hash }); // console.log(relativeFilePath + ' (size ' + size + ' bytes)'); diff --git a/lib/framework/ESP8266React.cpp b/lib/framework/ESP8266React.cpp index 94a3b78fd..6250a378f 100644 --- a/lib/framework/ESP8266React.cpp +++ b/lib/framework/ESP8266React.cpp @@ -19,15 +19,32 @@ ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) , _restartService(server, &_securitySettingsService) , _factoryResetService(server, fs, &_securitySettingsService) , _systemStatus(server, &_securitySettingsService) { - // Serve static resources - WWWData::registerRoutes([server, this](const String & uri, const String & contentType, const uint8_t * content, size_t len) { - ArRequestHandlerFunction requestHandler = [contentType, content, len](AsyncWebServerRequest * request) { + // + // Serve static web resources + // + + // Populate the last modification date based on build datetime + static char last_modified[50]; + sprintf(last_modified, "%s %s CET", __DATE__, __TIME__); + + WWWData::registerRoutes([server, this](const String & uri, const String & contentType, const uint8_t * content, size_t len, const String & hash) { + ArRequestHandlerFunction requestHandler = [contentType, content, len, hash](AsyncWebServerRequest * request) { + // Check if the client already has the same version and respond with a 304 (Not modified) + if (request->header("If-Modified-Since").indexOf(last_modified) > 0) { + return request->send(304); + } else if (request->header("If-None-Match").equals(hash)) { + return request->send(304); + } + AsyncWebServerResponse * response = request->beginResponse_P(200, contentType, content, len); response->addHeader("Content-Encoding", "gzip"); - response->addHeader("Cache-Control", "public, immutable, max-age=31536000"); + // response->addHeader("Cache-Control", "public, immutable, max-age=31536000"); + response->addHeader("Last-Modified", last_modified); + response->addHeader("ETag", hash); // response->addHeader("Content-Encoding", "br"); // only works over HTTPS request->send(response); }; + server->on(uri.c_str(), HTTP_GET, requestHandler); // Serving non matching get requests with "/index.html" // OPTIONS get a straight up 200 response diff --git a/lib_standalone/Network.h b/lib_standalone/Network.h index 6fa63c151..c7a750180 100644 --- a/lib_standalone/Network.h +++ b/lib_standalone/Network.h @@ -11,6 +11,21 @@ #define WIFI_AP WIFI_MODE_AP #define WIFI_AP_STA WIFI_MODE_APSTA +typedef enum { + WIFI_POWER_19_5dBm = 78, // 19.5dBm + WIFI_POWER_19dBm = 76, // 19dBm + WIFI_POWER_18_5dBm = 74, // 18.5dBm + WIFI_POWER_17dBm = 68, // 17dBm + WIFI_POWER_15dBm = 60, // 15dBm + WIFI_POWER_13dBm = 52, // 13dBm + WIFI_POWER_11dBm = 44, // 11dBm + WIFI_POWER_8_5dBm = 34, // 8.5dBm + WIFI_POWER_7dBm = 28, // 7dBm + WIFI_POWER_5dBm = 20, // 5dBm + WIFI_POWER_2dBm = 8, // 2dBm + WIFI_POWER_MINUS_1dBm = -4 // -1dBm +} wifi_power_t; + typedef enum { ETH_CLOCK_GPIO0_IN = 0, /*!< RMII clock input to GPIO0 */ ETH_CLOCK_GPIO0_OUT = 1, /*!< RMII clock output from GPIO0 */