/* * ESP8266 RGBW controller * Copyright 2020 (c) Mark van Renswoude * * https://git.x2software.net/pub/RGBWifi */ 'use strict'; const gulp = require('gulp'); const htmlmin = require('gulp-htmlmin'); const cppstringify = require('./gulp-cppstringify'); const fs = require('fs'); const plumber = require('gulp-plumber'); const sass = require('gulp-sass'); const cleanCSS = require('gulp-clean-css'); const watch = require('gulp-debounced-watch'); const uglify = require('gulp-uglify'); const concat = require('gulp-concat'); const print = require('gulp-print'); const path = require('path'); const gzip = require('gulp-gzip'); const webpack = require('webpack') const webpackConfig = require('./webpack.build.js') const config = { distPath: 'web/dist/', outputPath: 'src/assets/', firmwareArtifact: '.pio/build/esp12e/firmware.bin', firmwareOutputPath: 'bin/' }; function runWebpack() { return new Promise((resolve, reject) => { webpack(webpackConfig, (err, stats) => { if (err) return reject(err); if (stats.hasErrors()) return reject(new Error(stats.compilation.errors.join('\n'))); resolve() }); }); } const HTMLMap = { 'index.html': 'Index' }; const JSMap = { 'bundle.js': 'BundleJS' }; /* const CSSMap = { 'bundle.css': 'BundleCSS' }; */ /* // There is an issue in the AsyncWebServer where it's apparantly running // out of memory on simultaneous requests. We'll work around it by // merging all the JS into one big file. // // https://github.com/me-no-dev/ESPAsyncWebServer/issues/256 const JSSrc = [ 'node_modules/axios/dist/axios.min.js', 'node_modules/vue/dist/vue.min.js', 'node_modules/vue-i18n/dist/vue-i18n.min.js', 'web/lang.js', 'web/app.js' ]; const SCSSSrc = [ 'web/site.scss' ] */ function embedHTML() { return gulp.src(config.distPath + 'index.html') .pipe(print(filepath => { return 'HTML: ' + filepath; })) .pipe(htmlmin({ collapseWhitespace: true, removeComments: true, minifyCSS: true, minifyJS: true })) .pipe(gzip({ append: false })) .pipe(cppstringify('html.h', { headerDefineName: '__assets_html', map: HTMLMap, byteArray: true })) .pipe(gulp.dest(config.outputPath)); } /* gulp.task('compileScss', () => { return gulp.src(SCSSSrc) .pipe(plumber({ errorHandler: error => { console.log(error.toString()); this.emit('end'); }})) .pipe(print(filepath => { return 'SCSS: ' + filepath })) .pipe(sass({ includePaths: ['node_modules/milligram/src'] })) .pipe(cleanCSS({compatibility: 'ie9'})) .pipe(concat('bundle.css')) .pipe(gulp.dest(config.distPath)); }); gulp.task('compileJS', () => { return gulp.src(JSSrc) .pipe(plumber({ errorHandler: error => { console.log(error.toString()); this.emit('end'); }})) .pipe(print(filepath => { return 'JS: ' + filepath })) .pipe(concat('bundle.js')) .pipe(uglify()) .pipe(gulp.dest(config.distPath)); }); */ function embedJS() { return gulp.src([config.distPath + 'bundle.js']) .pipe(gzip({ append: false })) .pipe(cppstringify('js.h', { headerDefineName: '__assets_js', map: JSMap, byteArray: true })) .pipe(gulp.dest(config.outputPath)); } /* function embedCSS() { return gulp.src([config.distPath + 'bundle.css']) .pipe(gzip({ append: false })) .pipe(cppstringify('css.h', { headerDefineName: '__embed_css', map: CSSMap, byteArray: true })) .pipe(gulp.dest(config.outputPath)); } */ var version = false; function getVersion(callback) { return new Promise((resolve, reject) => { if (version !== false) { resolve(version); return; } var versionData = ''; const cmd = spawn('gitversion'); cmd.stdout.on('data', data => { versionData += data; }); cmd.stderr.on('data', data => { console.log(data.toString().trim()); }); cmd.on('exit', code => { if (code != 0) { reject(code); return; } var version = JSON.parse(versionData); Promise.resolve(callback(version)) .then(resolve) .catch(reject); }); }); } function embedVersion() { return getVersion(version => { return new Promise((resolve, reject) => { var headerFile = "#ifndef __assets_version\r\n"; headerFile += "#define __assets_version\r\n\r\n"; headerFile += "const uint8_t VersionMajor = " + version.Major + ";\r\n"; headerFile += "const uint8_t VersionMinor = " + version.Minor + ";\r\n"; headerFile += "const uint8_t VersionPatch = " + version.Patch + ";\r\n"; headerFile += "const uint8_t VersionMetadata = " + (version.BuildMetaData ? version.BuildMetaData : '0') + ";\r\n"; headerFile += "const char VersionBranch[] = \"" + version.BranchName + "\";\r\n"; headerFile += "const char VersionSemVer[] = \"" + version.SemVer + "\";\r\n"; headerFile += "const char VersionFullSemVer[] = \"" + version.FullSemVer + "\";\r\n"; headerFile += "const char VersionCommitDate[] = \"" + version.CommitDate + "\";\r\n"; headerFile += "\r\n#endif\r\n"; fs.writeFile(config.outputPath + 'version.h', headerFile, err => { if (err) reject(err); else resolve(); }); }) }); } function copyBinary() { if (!fs.existsSync(config.firmwareOutputPath)) fs.mkdirSync(config.firmwareOutputPath, '0777', true); return getVersion(version => { return new Promise((resolve, reject) => { var target = path.join(config.firmwareOutputPath, version.FullSemVer + '.bin'); console.log('Target: ' + target); var reader = fs.createReadStream(config.firmwareArtifact); reader.pipe(fs.createWriteStream(target)); reader.on('end', resolve); }); }); } // PlatformIO const spawn = require('child_process').spawn; const argv = require('yargs').argv; function platformio(target) { var args = ['run']; if ("e" in argv) { args.push('-e'); args.push(argv.e); } if ("p" in argv) { args.push('--upload-port'); args.push(argv.p); } if (target) { args.push('-t'); args.push(target); } return new Promise((resolve, reject) => { const cmd = spawn('platformio', args); cmd.stdout.on('data', data => { console.log(data.toString().trim()); }); cmd.stderr.on('data', data => { console.log(data.toString().trim()); }); cmd.on('exit', code => { if (code != 0) { reject(code); return; } return Promise.resolve(copyBinary()) .then(resolve) .catch(reject); }); }); } function platformIOUpload() { return platformio('upload'); } function platformIOBuild() { return platformio(false); } const buildAndEmbedAssets = gulp.series(runWebpack, embedHTML, embedJS, embedVersion); module.exports = { upload: gulp.series(buildAndEmbedAssets, platformIOUpload), build: gulp.series(buildAndEmbedAssets, platformIOBuild), default: gulp.series(buildAndEmbedAssets) };