Browse Source

Using gulp to generate the embedded web contents, added Last-Modifier support to embedded home

fastled
Xose Pérez 7 years ago
parent
commit
be1fac2f44
6 changed files with 85 additions and 54 deletions
  1. +2
    -2
      code/.gitignore
  2. +0
    -18
      code/build-data_h
  3. +7
    -1
      code/espurna/config/general.h
  4. +17
    -17
      code/espurna/espurna.ino
  5. +27
    -11
      code/espurna/web.ino
  6. +32
    -5
      code/gulpfile.js

+ 2
- 2
code/.gitignore View File

@ -1,4 +1,4 @@
.pioenvs
.pio*
.clang_complete .clang_complete
.gcc-flags.json .gcc-flags.json
.piolibdeps
espurna/config/data.h

+ 0
- 18
code/build-data_h View File

@ -1,18 +0,0 @@
#!/bin/python
import binascii
import string
source = 'espurna/data/index.html.gz'
destination = 'espurna/config/data.h'
with open(source, 'rb') as f:
content = f.read()
array = map(lambda x: '0x%02x' % ord(x), content)
with open(destination, 'w') as f:
f.write("#define index_html_gz_len %d\n" % len(array))
f.write("const uint8_t index_html_gz[] PROGMEM = {")
f.write(string.join(array, ','))
f.write("};\n")

+ 7
- 1
code/espurna/config/general.h View File

@ -103,7 +103,13 @@
#define AP_MODE_GW "192.168.4.1" #define AP_MODE_GW "192.168.4.1"
#define AP_MODE_MASK "255.255.255.0" #define AP_MODE_MASK "255.255.255.0"
#define EMBED_WEB_IN_FIRMWARE 0
// This option builds the firmware with the web interface embedded.
// You first have to build the data.h file that holds the contents
// of the web interface by running "gulp buildfs_embed"
#ifndef EMBEDDED_WEB
#define EMBEDDED_WEB 0
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// OTA & NOFUSS // OTA & NOFUSS


+ 17
- 17
code/espurna/espurna.ino View File

@ -21,12 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "config/all.h" #include "config/all.h"
// -----------------------------------------------------------------------------
// GLOBALS
// -----------------------------------------------------------------------------
char apibuffer[64];
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// METHODS // METHODS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -39,7 +33,9 @@ String getIdentifier() {
void hardwareSetup() { void hardwareSetup() {
Serial.begin(SERIAL_BAUDRATE); Serial.begin(SERIAL_BAUDRATE);
SPIFFS.begin();
#if not EMBEDDED_WEB
SPIFFS.begin();
#endif
} }
void hardwareLoop() { void hardwareLoop() {
@ -62,9 +58,9 @@ void hardwareLoop() {
void welcome() { void welcome() {
delay(2000); delay(2000);
DEBUG_MSG("%s %s\n", (char *) APP_NAME, (char *) APP_VERSION); DEBUG_MSG("%s %s\n", (char *) APP_NAME, (char *) APP_VERSION);
DEBUG_MSG("%s\n%s\n\n", (char *) APP_AUTHOR, (char *) APP_WEBSITE); DEBUG_MSG("%s\n%s\n\n", (char *) APP_AUTHOR, (char *) APP_WEBSITE);
//DEBUG_MSG("Device: %s\n", (char *) getIdentifier().c_str());
DEBUG_MSG("ChipID: %06X\n", ESP.getChipId()); DEBUG_MSG("ChipID: %06X\n", ESP.getChipId());
DEBUG_MSG("CPU frequency: %d MHz\n", ESP.getCpuFreqMHz()); DEBUG_MSG("CPU frequency: %d MHz\n", ESP.getCpuFreqMHz());
DEBUG_MSG("Last reset reason: %s\n", (char *) ESP.getResetReason().c_str()); DEBUG_MSG("Last reset reason: %s\n", (char *) ESP.getResetReason().c_str());
@ -72,15 +68,19 @@ void welcome() {
DEBUG_MSG("Free heap: %d bytes\n", ESP.getFreeHeap()); DEBUG_MSG("Free heap: %d bytes\n", ESP.getFreeHeap());
DEBUG_MSG("Firmware size: %d bytes\n", ESP.getSketchSize()); DEBUG_MSG("Firmware size: %d bytes\n", ESP.getSketchSize());
DEBUG_MSG("Free firmware space: %d bytes\n", ESP.getFreeSketchSpace()); DEBUG_MSG("Free firmware space: %d bytes\n", ESP.getFreeSketchSpace());
FSInfo fs_info;
if (SPIFFS.info(fs_info)) {
DEBUG_MSG("File system total size: %d bytes\n", fs_info.totalBytes);
DEBUG_MSG(" used size : %d bytes\n", fs_info.usedBytes);
DEBUG_MSG(" block size: %d bytes\n", fs_info.blockSize);
DEBUG_MSG(" page size : %d bytes\n", fs_info.pageSize);
DEBUG_MSG(" max files : %d\n", fs_info.maxOpenFiles);
DEBUG_MSG(" max length: %d\n", fs_info.maxPathLength);
}
#if not EMBEDDED_WEB
FSInfo fs_info;
if (SPIFFS.info(fs_info)) {
DEBUG_MSG("File system total size: %d bytes\n", fs_info.totalBytes);
DEBUG_MSG(" used size : %d bytes\n", fs_info.usedBytes);
DEBUG_MSG(" block size: %d bytes\n", fs_info.blockSize);
DEBUG_MSG(" page size : %d bytes\n", fs_info.pageSize);
DEBUG_MSG(" max files : %d\n", fs_info.maxOpenFiles);
DEBUG_MSG(" max length: %d\n", fs_info.maxPathLength);
}
#endif
DEBUG_MSG("\n\n"); DEBUG_MSG("\n\n");
} }


+ 27
- 11
code/espurna/web.ino View File

@ -16,7 +16,7 @@ Copyright (C) 2016-2017 by Xose Pérez <xose dot perez at gmail dot com>
#include <Ticker.h> #include <Ticker.h>
#include <vector> #include <vector>
#if EMBED_WEB_IN_FIRMWARE == 1
#if EMBEDDED_WEB
#include "config/data.h" #include "config/data.h"
#endif #endif
@ -37,6 +37,7 @@ typedef struct {
apiPutCallbackFunction putFn = NULL; apiPutCallbackFunction putFn = NULL;
} web_api_t; } web_api_t;
std::vector<web_api_t> _apis; std::vector<web_api_t> _apis;
char _last_modified[50];
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// WEBSOCKETS // WEBSOCKETS
@ -706,12 +707,26 @@ void _onAuth(AsyncWebServerRequest *request) {
} }
#if EMBED_WEB_IN_FIRMWARE == 1
#if EMBEDDED_WEB
void _onHome(AsyncWebServerRequest *request) { void _onHome(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html_gz, index_html_gz_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
webLogRequest(request);
if (request->header("If-Modified-Since").equals(_last_modified)) {
request->send(304);
} else {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html_gz, index_html_gz_len);
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Last-Modified", _last_modified);
request->send(response);
}
} }
#endif #endif
void webSetup() { void webSetup() {
@ -723,6 +738,9 @@ void webSetup() {
ws.onEvent(_wsEvent); ws.onEvent(_wsEvent);
mqttRegister(wsMQTTCallback); mqttRegister(wsMQTTCallback);
// Cache the Last-Modifier header value
sprintf(_last_modified, "%s %s GMT", __DATE__, __TIME__);
// Setup webserver // Setup webserver
_server->addHandler(&ws); _server->addHandler(&ws);
@ -730,19 +748,17 @@ void webSetup() {
_server->rewrite("/", "/index.html"); _server->rewrite("/", "/index.html");
// Serve home (basic authentication protection) // Serve home (basic authentication protection)
#if EMBED_WEB_IN_FIRMWARE == 1
_server->on("/index.html", HTTP_GET, _onHome);
#if EMBEDDED_WEB
_server->on("/index.html", HTTP_GET, _onHome);
#endif #endif
_server->on("/auth", HTTP_GET, _onAuth); _server->on("/auth", HTTP_GET, _onAuth);
_server->on("/apis", HTTP_GET, _onAPIs); _server->on("/apis", HTTP_GET, _onAPIs);
_server->on("/rpc", HTTP_GET, _onRPC); _server->on("/rpc", HTTP_GET, _onRPC);
// Serve static files // Serve static files
#if EMBED_WEB_IN_FIRMWARE == 0
char lastModified[50];
sprintf(lastModified, "%s %s GMT", __DATE__, __TIME__);
#if not EMBEDDED_WEB
_server->serveStatic("/", SPIFFS, "/") _server->serveStatic("/", SPIFFS, "/")
.setLastModified(lastModified)
.setLastModified(_last_modified)
.setFilter([](AsyncWebServerRequest *request) -> bool { .setFilter([](AsyncWebServerRequest *request) -> bool {
webLogRequest(request); webLogRequest(request);
return true; return true;


+ 32
- 5
code/gulpfile.js View File

@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// File system builder // File system builder
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const fs = require('fs');
const gulp = require('gulp'); const gulp = require('gulp');
const plumber = require('gulp-plumber'); const plumber = require('gulp-plumber');
const htmlmin = require('gulp-htmlmin'); const htmlmin = require('gulp-htmlmin');
@ -36,11 +37,11 @@ const inline = require('gulp-inline');
const inlineImages = require('gulp-css-base64'); const inlineImages = require('gulp-css-base64');
const favicon = require('gulp-base64-favicon'); const favicon = require('gulp-base64-favicon');
const destination = 'espurna/data/';
const dataFolder = 'espurna/data/';
/* Clean destination folder */ /* Clean destination folder */
gulp.task('clean', function() { gulp.task('clean', function() {
del([ destination + '*']);
del([ dataFolder + '*']);
return true; return true;
}); });
@ -50,7 +51,32 @@ gulp.task('files', function() {
'html/**/*.{jpg,jpeg,png,ico,gif}', 'html/**/*.{jpg,jpeg,png,ico,gif}',
'html/fsversion' 'html/fsversion'
]) ])
.pipe(gulp.dest(destination));
.pipe(gulp.dest(dataFolder));
});
gulp.task('embed', function() {
var source = dataFolder + 'index.html.gz';
var destination = dataFolder + '../config/data.h';
var wstream = fs.createWriteStream(destination);
wstream.on('error', function (err) {
console.log(err);
});
var data = fs.readFileSync(source);
wstream.write('#define index_html_gz_len ' + data.length + '\n');
wstream.write('const uint8_t index_html_gz[] PROGMEM = {')
for (i=0; i<data.length; i++) {
wstream.write('0x' + ('00' + data[i].toString(16)).slice(-2));
if (i<data.length-1) wstream.write(',');
}
wstream.write('};\n')
wstream.end();
}); });
gulp.task('inline_images', function() { gulp.task('inline_images', function() {
@ -78,7 +104,7 @@ gulp.task('inline', function() {
minifyJS: true minifyJS: true
})) }))
.pipe(gzip()) .pipe(gzip())
.pipe(gulp.dest(destination));
.pipe(gulp.dest(dataFolder));
}) })
/* Process HTML, CSS, JS */ /* Process HTML, CSS, JS */
@ -95,10 +121,11 @@ gulp.task('html', function() {
minifyJS: true minifyJS: true
}))) })))
.pipe(gzip()) .pipe(gzip())
.pipe(gulp.dest(destination));
.pipe(gulp.dest(dataFolder));
}); });
/* Build file system */ /* Build file system */
gulp.task('buildfs_split', ['clean', 'files', 'html']); gulp.task('buildfs_split', ['clean', 'files', 'html']);
gulp.task('buildfs_inline', ['clean', 'inline_images', 'inline']); gulp.task('buildfs_inline', ['clean', 'inline_images', 'inline']);
gulp.task('buildfs_embed', ['buildfs_inline', 'embed']);
gulp.task('default', ['buildfs_inline']); gulp.task('default', ['buildfs_inline']);

Loading…
Cancel
Save