diff --git a/.gitignore b/.gitignore index d600de31..439d23ef 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ firmware* .pioenvs .sconsign.dblite +node_modules diff --git a/README.md b/README.md index 9dfdd44c..1f9234cd 100644 --- a/README.md +++ b/README.md @@ -30,21 +30,31 @@ You can read about this board and firmware in [my blog][2]. * Support for **DHT22** sensors * Command line configuration -# Flashing a Sonoff +## Installing -*This section only applies to the Sonoff, but pretty much every other ESP8266-based hardware will be similar.* +### Build the web config site -The unpopulated header in the Sonoff has all the required pins. My board has a 5 pins header in-line with the button. They are (from the button outwards): +Normally when you flash an ESP8266 you only flash the firmware, like for any other microcontroller. But the ESP8266 has plenty of room and normally it is split into different partitions. One such partition is used to store web files like a normal webserver. In the "Flash your board" section below you'll know how to flash this special partition, but first we will have to build it. -* 3V3 -* RX -* TX -* GND -* GPIO14 +The build process read the HTML files, looks for the stylesheet and script files linked there, grabs them, merges them, minifies them and compresses them. Thus, a single HTML with N linked scripts and M linked CSS files is transformed in just 3 files (index.html.gz, style.css.gz and script.js.gz). This way the ESP8266 webserver can serve them really fast. Mind the ESP8266 is just a microcontroller, the webserver has a very limited capacity to hold concurrent requests, so few and lighter files are a must. -Last one is not necessary. Mind it's a **3V3 device**, if connected to 5V you will probably fry it. Button is connected to GPIO0 on the ESP8266 chip, so to enter flash mode you have to hold the button pressed while powering on the board, then you can realease it again. +To build these files we are using **[Gulp][11]**, a build system built in [node.js][13]. So you will need node (and [npm][14], its package manager) first. [Read the documentation][12] on how to install them. + +Once you have node and npm installed, go to the 'code' folder and install all the dependencies with: + +``` +npm install +``` + +It will take a minute or two. Then you are ready to build the webserver files with: + +``` +gulp +``` -## Firmware +It will create a populate a 'data' folder with all the required files. + +### Build the firmware The project is ready to be build using [PlatformIO][3]. Please refer to their web page for instructions on how to install the builder. @@ -75,7 +85,23 @@ Once you have all the code, you can check if it's working by: > platformio run -e node-debug ``` -If it compiles you are ready to flash, wire your board like in the flashing section above and: +If it compiles you are ready to flash the firmware. + +### Flash your board + +*This section only applies to the Sonoff, but pretty much every other ESP8266-based hardware will be similar.* + +The unpopulated header in the Sonoff has all the required pins. My board has a 5 pins header in-line with the button. They are (from the button outwards): + +* 3V3 +* RX +* TX +* GND +* GPIO14 + +Last one is not necessary. Mind it's a **3V3 device**, if connected to 5V you will probably fry it. Button is connected to GPIO0 on the ESP8266 chip, so to enter flash mode you have to hold the button pressed while powering on the board, then you can realease it again. + +Wire your board and flash the firmware (with ```upload```) and the file system (with ```uploadfs```): ```bash > platformio run --target upload -e node-debug @@ -127,3 +153,7 @@ After flashing the firmware via serial do a hard reset of the device (unplug & p [8]: https://www.itead.cc/sonoff-rf.html [9]: https://www.itead.cc/slampher-wifi-wireless-light-holder.html [10]: https://www.itead.cc/smart-socket-eu.html +[11]: http://gulpjs.com/ +[12]: https://docs.npmjs.com/getting-started/installing-node +[13]: https://nodejs.org/en/ +[14]: https://www.npmjs.com/ diff --git a/code/data/checkboxes-min.css.gz b/code/data/checkboxes-min.css.gz deleted file mode 100644 index 5ffa7577..00000000 Binary files a/code/data/checkboxes-min.css.gz and /dev/null differ diff --git a/code/data/checkboxes-min.js.gz b/code/data/checkboxes-min.js.gz deleted file mode 100644 index 250e37e2..00000000 Binary files a/code/data/checkboxes-min.js.gz and /dev/null differ diff --git a/code/data/favicon.ico b/code/data/favicon.ico deleted file mode 100644 index ee8bae72..00000000 Binary files a/code/data/favicon.ico and /dev/null differ diff --git a/code/data/grids-responsive-min.css.gz b/code/data/grids-responsive-min.css.gz deleted file mode 100644 index a189cb95..00000000 Binary files a/code/data/grids-responsive-min.css.gz and /dev/null differ diff --git a/code/data/images/off.png b/code/data/images/off.png deleted file mode 100644 index f414051e..00000000 Binary files a/code/data/images/off.png and /dev/null differ diff --git a/code/data/images/on.png b/code/data/images/on.png deleted file mode 100644 index 94425e58..00000000 Binary files a/code/data/images/on.png and /dev/null differ diff --git a/code/data/images/slider.png b/code/data/images/slider.png deleted file mode 100644 index 80e05ff2..00000000 Binary files a/code/data/images/slider.png and /dev/null differ diff --git a/code/data/images/slider_center.png b/code/data/images/slider_center.png deleted file mode 100644 index 310fc8cc..00000000 Binary files a/code/data/images/slider_center.png and /dev/null differ diff --git a/code/data/images/slider_left.png b/code/data/images/slider_left.png deleted file mode 100644 index 51576ce3..00000000 Binary files a/code/data/images/slider_left.png and /dev/null differ diff --git a/code/data/images/slider_right.png b/code/data/images/slider_right.png deleted file mode 100644 index 447d94a6..00000000 Binary files a/code/data/images/slider_right.png and /dev/null differ diff --git a/code/data/index.html.gz b/code/data/index.html.gz deleted file mode 100644 index 0a896514..00000000 Binary files a/code/data/index.html.gz and /dev/null differ diff --git a/code/data/jquery-1.12.3.min.js.gz b/code/data/jquery-1.12.3.min.js.gz deleted file mode 100644 index 29b86ef9..00000000 Binary files a/code/data/jquery-1.12.3.min.js.gz and /dev/null differ diff --git a/code/data/pure-min.css.gz b/code/data/pure-min.css.gz deleted file mode 100644 index 25ffd50e..00000000 Binary files a/code/data/pure-min.css.gz and /dev/null differ diff --git a/code/data/side-menu-min.css.gz b/code/data/side-menu-min.css.gz deleted file mode 100644 index 12273a82..00000000 Binary files a/code/data/side-menu-min.css.gz and /dev/null differ diff --git a/code/gulpfile.js b/code/gulpfile.js new file mode 100644 index 00000000..f127089d --- /dev/null +++ b/code/gulpfile.js @@ -0,0 +1,43 @@ +var gulp = require('gulp'); +var plumber = require('gulp-plumber'); +var htmlmin = require('gulp-htmlmin'); +var cleancss = require('gulp-clean-css'); +var uglify = require('gulp-uglify'); +var gzip = require('gulp-gzip'); +var del = require('del'); +var useref = require('gulp-useref'); +var gulpif = require('gulp-if'); + +/* Clean destination folder */ +gulp.task('clean', function() { + return del(['data/*']); +}); + +/* Copy static files */ +gulp.task('files', function() { + return gulp.src([ + 'html/**/*.{jpg,jpeg,png,ico,gif}', + 'html/fsversion' + ]) + .pipe(gulp.dest('data/')); +}); + +/* Process HTML, CSS, JS */ +gulp.task('html', function() { + return gulp.src('html/*.html') + .pipe(useref()) + .pipe(plumber()) + .pipe(gulpif('*.css', cleancss())) + .pipe(gulpif('*.js', uglify())) + .pipe(gulpif('*.html', htmlmin({ + collapseWhitespace: true, + removeComments: true, + minifyCSS: true, + minifyJS: true + }))) + .pipe(gzip()) + .pipe(gulp.dest('data')); +}); + +/* Default Task */ +gulp.task('default', ['clean', 'files', 'html']); diff --git a/code/html/checkboxes-min.css b/code/html/checkboxes-min.css deleted file mode 100644 index 311f2e2f..00000000 --- a/code/html/checkboxes-min.css +++ /dev/null @@ -1 +0,0 @@ -.iPhoneCheckContainer{-webkit-transform:translate3d(0,0,0);position:relative;height:27px;cursor:pointer;overflow:hidden}.iPhoneCheckContainer input{position:absolute;top:5px;left:30px;filter:alpha(Opacity=0);opacity:0}.iPhoneCheckContainer label,.iPhoneCheckHandle{display:block;height:27px;cursor:pointer;position:absolute;top:0}.iPhoneCheckContainer label{white-space:nowrap;font-size:17px;line-height:17px;font-weight:700;font-family:"Helvetica Neue",Arial,Helvetica,sans-serif;width:auto;padding-top:5px;overflow:hidden}.iPhoneCheckContainer,.iPhoneCheckContainer label{user-select:none;-moz-user-select:none;-khtml-user-select:none}.iPhoneCheckDisabled{filter:alpha(Opacity=50);opacity:.5}label.iPhoneCheckLabelOn{color:#fff;background:url(images/on.png) no-repeat;text-shadow:0 0 2px rgba(0,0,0,.6);left:0;padding-top:5px}label.iPhoneCheckLabelOn span{padding-left:8px}label.iPhoneCheckLabelOff{color:#8b8b8b;background:url(images/off.png) right 0 no-repeat;text-shadow:0 0 2px rgba(255,255,255,.6);text-align:right;right:0}label.iPhoneCheckLabelOff span{padding-right:8px}.iPhoneCheckHandle{left:0;width:0;background:url(images/slider_left.png) no-repeat;padding-left:3px}.iPhoneCheckHandleRight{height:100%;width:100%;padding-right:3px;background:url(images/slider_right.png) right 0 no-repeat}.iPhoneCheckHandleCenter{height:100%;width:100%;background:url(images/slider_center.png)} \ No newline at end of file diff --git a/code/html/checkboxes-min.js b/code/html/checkboxes-min.js deleted file mode 100644 index 013487c3..00000000 --- a/code/html/checkboxes-min.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var e,i,t,n=[].slice;null==$.browser&&(t=navigator.userAgent||"",jQuery.uaMatch=function(e){var i;return e=e.toLowerCase(),i=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(e)||[],{browser:i[1]||"",version:i[2]||"0"}},i=jQuery.uaMatch(t),jQuery.browser={},i.browser&&(jQuery.browser[i.browser]=!0,jQuery.browser.version=i.version),jQuery.browser.webkit&&(jQuery.browser.safari=!0)),e=function(){function e(i,t){var n,s,a;this.elem=$(i),s=$.extend({},e.defaults,t);for(n in s)a=s[n],this[n]=a;this.elem.data(this.dataName,this),this.wrapCheckboxWithDivs(),this.attachEvents(),this.disableTextSelection(),this.calculateDimensions()}return e.prototype.calculateDimensions=function(){return this.resizeHandle&&this.optionallyResize("handle"),this.resizeContainer&&this.optionallyResize("container"),this.initialPosition()},e.prototype.isDisabled=function(){return this.elem.is(":disabled")},e.prototype.wrapCheckboxWithDivs=function(){return this.elem.wrap("
"),this.container=this.elem.parent(),this.offLabel=$("").appendTo(this.container),this.offSpan=this.offLabel.children("span"),this.onLabel=$("").appendTo(this.container),this.onSpan=this.onLabel.children("span"),this.handle=$("