Переглянути джерело

Merge branch 'newdocs' into dev

Marcel Stör 8 роки тому
батько
коміт
82b19c4c37
50 змінених файлів з 5680 додано та 170 видалено
  1. 1 167
      README.md
  2. 3 3
      app/modules/bmp085.c
  3. 42 0
      docs/css/extra.css
  4. 6 0
      docs/de/index.md
  5. 10 0
      docs/en/build.md
  6. 20 0
      docs/en/faq.md
  7. 31 0
      docs/en/flash.md
  8. 51 0
      docs/en/index.md
  9. 39 0
      docs/en/modules/adc.md
  10. 170 0
      docs/en/modules/bit.md
  11. 67 0
      docs/en/modules/bmp085.md
  12. 49 0
      docs/en/modules/cjson.md
  13. 224 0
      docs/en/modules/coap.md
  14. 110 0
      docs/en/modules/crypto.md
  15. 93 0
      docs/en/modules/dht.md
  16. 47 0
      docs/en/modules/enduser-setup.md
  17. 331 0
      docs/en/modules/file.md
  18. 157 0
      docs/en/modules/gpio.md
  19. 165 0
      docs/en/modules/http.md
  20. 48 0
      docs/en/modules/hx711.md
  21. 130 0
      docs/en/modules/i2c.md
  22. 152 0
      docs/en/modules/mqtt.md
  23. 284 0
      docs/en/modules/net.md
  24. 380 0
      docs/en/modules/node.md
  25. 271 0
      docs/en/modules/ow.md
  26. 152 0
      docs/en/modules/pwm.md
  27. 2 0
      docs/en/modules/rtcfifo.md
  28. 59 0
      docs/en/modules/rtcmem.md
  29. 6 0
      docs/en/modules/rtctime.md
  30. 40 0
      docs/en/modules/sntp.md
  31. 173 0
      docs/en/modules/spi.md
  32. 273 0
      docs/en/modules/tmr.md
  33. 131 0
      docs/en/modules/tsl2561.md
  34. 286 0
      docs/en/modules/u8g.md
  35. 103 0
      docs/en/modules/uart.md
  36. 266 0
      docs/en/modules/ucg.md
  37. 933 0
      docs/en/modules/wifi.md
  38. 37 0
      docs/en/modules/ws2801.md
  39. 53 0
      docs/en/modules/ws2812.md
  40. 5 0
      docs/en/start.md
  41. 7 0
      docs/en/support.md
  42. 35 0
      docs/en/upload.md
  43. BIN
      docs/img/ESPlorer.jpg
  44. BIN
      docs/img/enduser-setup.jpg
  45. BIN
      docs/img/favicon.png
  46. BIN
      docs/img/logo-small.png
  47. BIN
      docs/img/logo.png
  48. 15 0
      docs/index.md
  49. 158 0
      docs/js/extra.js
  50. 65 0
      mkdocs.yml

+ 1 - 167
README.md

@@ -2,6 +2,7 @@
 
 [![Join the chat at https://gitter.im/nodemcu/nodemcu-firmware](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nodemcu/nodemcu-firmware?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Build Status](https://travis-ci.org/nodemcu/nodemcu-firmware.svg)](https://travis-ci.org/nodemcu/nodemcu-firmware)
+[![Documentation Status](https://readthedocs.org/projects/nodemcu/badge/?version=newdocs)](http://nodemcu.readthedocs.org/en/newdocs/?badge=newdocs)
 
 ###A lua based firmware for wifi-soc esp8266
   - Build on [ESP8266 NONOS SDK 1.5.1](http://bbs.espressif.com/viewtopic.php?f=46&p=5315)
@@ -411,173 +412,6 @@ Victor Brutskiy's [ESPlorer](https://github.com/4refr0nt/ESPlorer) is written in
     package.loaded["ds18b20"]=nil
 ```
 
-####Operate a display with u8glib
-u8glib is a graphics library with support for many different displays. The nodemcu firmware supports a subset of these.
-Both I2C and SPI:
-* sh1106_128x64
-* ssd1306 - 128x64 and 64x48 variants
-* ssd1309_128x64
-* ssd1327_96x96_gr
-* uc1611 - dogm240 and dogxl240 variants
-
-SPI only:
-* ld7032_60x32
-* pcd8544_84x48
-* pcf8812_96x65
-* ssd1322_nhd31oled - bw and gr variants
-* ssd1325_nhd27oled - bw and gr variants
-* ssd1351_128x128 - gh and hicolor variants
-* st7565_64128n - variants 64128n, dogm128/132, lm6059/lm6063, c12832/c12864
-* uc1601_c128032
-* uc1608 - 240x128 and 240x64 variants
-* uc1610_dogxl160 - bw and gr variants
-* uc1611 - dogm240 and dogxl240 variants
-* uc1701 - dogs102 and mini12864 variants
-
-U8glib v1.18.1
-
-#####I2C connection
-Hook up SDA and SCL to any free GPIOs. Eg. [u8g_graphics_test.lua](lua_examples/u8glib/u8g_graphics_test.lua) expects SDA=5 (GPIO14) and SCL=6 (GPIO12). They are used to set up nodemcu's I2C driver before accessing the display:
-```lua
-sda = 5
-scl = 6
-i2c.setup(0, sda, scl, i2c.SLOW)
-```
-
-#####SPI connection
-The HSPI module is used ([more information](http://d.av.id.au/blog/esp8266-hardware-spi-hspi-general-info-and-pinout/)), so certain pins are fixed:
-* HSPI CLK  = GPIO14
-* HSPI MOSI = GPIO13
-* HSPI MISO = GPIO12 (not used)
-
-All other pins can be assigned to any available GPIO:
-* CS
-* D/C
-* RES (optional for some displays)
-
-Also refer to the initialization sequence eg in [u8g_graphics_test.lua](lua_examples/u8glib/u8g_graphics_test.lua):
-```lua
-spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
-```
-
-
-#####Library usage
-The Lua bindings for this library closely follow u8glib's object oriented C++ API. Based on the u8g class, you create an object for your display type.
-
-SSD1306 via I2C:
-```lua
-sla = 0x3c
-disp = u8g.ssd1306_128x64_i2c(sla)
-```
-SSD1306 via SPI:
-```lua
-cs  = 8 -- GPIO15, pull-down 10k to GND
-dc  = 4 -- GPIO2
-res = 0 -- GPIO16, RES is optional YMMV
-disp = u8g.ssd1306_128x64_hw_spi(cs, dc, res)
-```
-
-This object provides all of u8glib's methods to control the display.
-Again, refer to [u8g_graphics_test.lua](lua_examples/u8glib/u8g_graphics_test.lua) to get an impression how this is achieved with Lua code. Visit the [u8glib homepage](https://github.com/olikraus/u8glib) for technical details.
-
-#####Displays
-I2C and HW SPI based displays with support in u8glib can be enabled. To get access to the respective constructors, add the desired entries to the I2C or SPI display tables in [app/include/u8g_config.h](app/include/u8g_config.h):
-```c
-#define U8G_DISPLAY_TABLE_I2C                   \
-    U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_i2c) \
-
-#define U8G_DISPLAY_TABLE_SPI                      \
-    U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_hw_spi) \
-    U8G_DISPLAY_TABLE_ENTRY(pcd8544_84x48_hw_spi)  \
-    U8G_DISPLAY_TABLE_ENTRY(pcf8812_96x65_hw_spi)  \
-```
-An exhaustive list of available displays can be found in the [u8g module wiki entry](https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_en#u8g-module).
-
-
-#####Fonts
-u8glib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in [app/include/u8g_config.h](app/include/u8g_config.h) and recompile. Simply add the desired fonts to the font table:
-```c
-#define U8G_FONT_TABLE \
-    U8G_FONT_TABLE_ENTRY(font_6x10)  \
-    U8G_FONT_TABLE_ENTRY(font_chikita)
-```
-They'll be available as `u8g.<font_name>` in Lua.
-
-#####Bitmaps
-Bitmaps and XBMs are supplied as strings to `drawBitmap()` and `drawXBM()`. This off-loads all data handling from the u8g module to generic methods for binary files. See [u8g_bitmaps.lua](lua_examples/u8glib/u8g_bitmaps.lua).
-In contrast to the source code based inclusion of XBMs into u8glib, it's required to provide precompiled binary files. This can be performed online with [Online-Utility's Image Converter](http://www.online-utility.org/image_converter.jsp): Convert from XBM to MONO format and upload the binary result with [nodemcu-uploader.py](https://github.com/kmpm/nodemcu-uploader).
-
-#####Unimplemented functions
-- [ ] Cursor handling
-  - [ ] disableCursor()
-  - [ ] enableCursor()
-  - [ ] setCursorColor()
-  - [ ] setCursorFont()
-  - [ ] setCursorPos()
-  - [ ] setCursorStyle()
-- [ ] General functions
-  - [ ] setContrast()
-  - [ ] setPrintPos()
-  - [ ] setHardwareBackup()
-  - [ ] setRGB()
-  - [ ] setDefaultMidColor()
-
-####Operate a display with ucglib
-Ucglib is a graphics library with support for color TFT displays.
-
-Ucglib v1.3.3
-
-#####SPI connection
-The HSPI module is used ([more information](http://d.av.id.au/blog/esp8266-hardware-spi-hspi-general-info-and-pinout/)), so certain pins are fixed:
-* HSPI CLK  = GPIO14
-* HSPI MOSI = GPIO13
-* HSPI MISO = GPIO12 (not used)
-
-All other pins can be assigned to any available GPIO:
-* CS
-* D/C
-* RES (optional for some displays)
-
-Also refer to the initialization sequence eg in [GraphicsTest.lua](lua_examples/ucglib/GraphicsRest.lua):
-```lua
-spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
-```
-
-#####Library usage
-The Lua bindings for this library closely follow ucglib's object oriented C++ API. Based on the ucg class, you create an object for your display type.
-
-ILI9341 via SPI:
-```lua
-cs  = 8 -- GPIO15, pull-down 10k to GND
-dc  = 4 -- GPIO2
-res = 0 -- GPIO16, RES is optional YMMV
-disp = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)
-```
-
-This object provides all of ucglib's methods to control the display.
-Again, refer to [GraphicsTest.lua](lua_examples/ucglib/GraphicsTest.lua) to get an impression how this is achieved with Lua code. Visit the [ucglib homepage](https://github.com/olikraus/ucglib) for technical details.
-
-#####Displays
-To get access to the display constructors, add the desired entries to the display table in [app/include/ucg_config.h](app/include/ucg_config.h):
-```c
-#define UCG_DISPLAY_TABLE                          \
-    UCG_DISPLAY_TABLE_ENTRY(ili9341_18x240x320_hw_spi, ucg_dev_ili9341_18x240x320, ucg_ext_ili9341_18) \
-    UCG_DISPLAY_TABLE_ENTRY(st7735_18x128x160_hw_spi, ucg_dev_st7735_18x128x160, ucg_ext_st7735_18) \
-```
-
-#####Fonts
-ucglib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in [app/include/ucg_config.h](app/include/ucg_config.h) and recompile. Simply add the desired fonts to the font table:
-```c
-#define UCG_FONT_TABLE                              \
-    UCG_FONT_TABLE_ENTRY(font_7x13B_tr)             \
-    UCG_FONT_TABLE_ENTRY(font_helvB12_hr)           \
-    UCG_FONT_TABLE_ENTRY(font_helvB18_hr)           \
-    UCG_FONT_TABLE_ENTRY(font_ncenR12_tr)           \
-    UCG_FONT_TABLE_ENTRY(font_ncenR14_hr)
-```
-They'll be available as `ucg.<font_name>` in Lua.
-
-
 ####Control a WS2812 based light strip
 ```lua
 	-- set the color of one LED on GPIO2 to red

+ 3 - 3
app/modules/bmp085.c

@@ -74,7 +74,7 @@ static int ICACHE_FLASH_ATTR bmp085_init(lua_State* L) {
     bmp085_data.MC  = r16(bmp085_i2c_id, 0xBC);
     bmp085_data.MD  = r16(bmp085_i2c_id, 0xBE);
 
-    return 1;
+    return 0;
 }
 
 static uint32_t bmp085_temperature_raw_b5(void) {
@@ -128,7 +128,7 @@ static int32_t ICACHE_FLASH_ATTR bmp085_pressure_raw(int oss) {
     p3 = r8u(bmp085_i2c_id, 0xF8);
     p = (p1 << 16) | (p2 << 8) | p3;
     p = p >> (8 - oss);
- 
+
     return p;
 }
 
@@ -159,7 +159,7 @@ static int ICACHE_FLASH_ATTR bmp085_lua_pressure(lua_State* L) {
             oss = 3;
         }
     }
- 
+
     p = bmp085_pressure_raw(oss);
     B5 = bmp085_temperature_raw_b5();
 

+ 42 - 0
docs/css/extra.css

@@ -0,0 +1,42 @@
+blockquote {
+  padding: 0 15px;
+  color: #777;
+  border-left: 4px solid #ddd;
+}
+
+.rst-content blockquote {
+  margin: 0;
+}
+
+/*shifts the nested subnav label to the left to align it with the regular nav item labels*/
+ul.subnav ul.subnav span {
+  padding-left: 1.3em;
+}
+
+body {
+  font-size: 100%;
+}
+p {
+  line-height: 20px;
+  margin-bottom: 16px;
+}
+h1, h2 {
+  border-bottom: 1px solid #eee;
+  line-height: 1.2;
+  margin-top: 1.2em;
+  margin-bottom: 16px;
+}
+h3, h4, h5, h6 {
+  margin: 1em 0 0.7em 0;
+}
+code {
+  font-size: 85%;
+  margin-right: 3px;
+}
+table.docutils td code {
+  font-size: 100%;
+}
+.wy-plain-list-disc, .rst-content .section ul, .rst-content .toctree-wrapper ul, article ul {
+  line-height: 20px;
+  margin-bottom: 16px;
+}

+ 6 - 0
docs/de/index.md

@@ -0,0 +1,6 @@
+# NodeMCU Dokumentation
+
+NodeMCU ist eine [eLua](http://www.eluaproject.net/)-basierende firmware für den [ESP8266 WiFi SOC von Espressif](http://espressif.com/en/products/esp8266/). Dies ist ein Partnerprojekt für die beliebten [NodeMCU dev kits](https://github.com/nodemcu/nodemcu-devkit-v1.0) - open source NodeMCU boards mit ESP8266-12E chips.
+
+Diese firmware nutzt das Espressif NON-OS SDK, das Dateisystem basiert auf [spiffs](https://github.com/pellepl/spiffs).
+

+ 10 - 0
docs/en/build.md

@@ -0,0 +1,10 @@
+There are essentially three ways to build your NodeMCU firmware: cloud build service, Docker image, dedicated Linux environment (possibly VM).
+
+## Cloud Build Service
+NodeMCU "application developers" just need a ready-made firmware. There's a [cloud build service](http://nodemcu-build.com/) with a nice UI and configuration options for them.
+
+## Docker Image
+Occasional NodeMCU firmware hackers don't need full control over the complete tool chain. They might not want to setup a Linux VM with the build environment. Docker to the rescue. Give [Docker NodeMCU build](https://hub.docker.com/r/marcelstoer/nodemcu-build/) a try.
+
+## Linux Build Environment
+NodeMCU firmware developers commit or contribute to the project on GitHub and might want to build their own full fledged build environment with the complete tool chain. There is a [post in the esp8266.com Wiki](http://www.esp8266.com/wiki/doku.php?id=toolchain#how_to_setup_a_vm_to_host_your_toolchain) that describes this.

Різницю між файлами не показано, бо вона завелика
+ 20 - 0
docs/en/faq.md


+ 31 - 0
docs/en/flash.md

@@ -0,0 +1,31 @@
+Adafruit provides a really nice [firmware flashing tutorial](https://learn.adafruit.com/building-and-running-micropython-on-the-esp8266/flash-firmware). Below you'll find just the basics for the two popular tools esptool and NodeMCU Flasher.
+
+!!! note "Note:"
+
+    Keep in mind that the ESP8266 needs to be put into flash mode before you can flash a new firmware!
+
+To enable ESP8266 firmware flashing GPIO0 pin must be pulled low before the device is reset. Conversely, for a normal boot, GPIO0 must be pulled high or floating.
+
+If you have a [NodeMCU dev kit](https://github.com/nodemcu/nodemcu-devkit-v1.0) then you don't need to do anything, as the USB connection can pull GPIO0 low by asserting DTR and reset your board by asserting RTS.
+
+If you have an ESP-01 or other device without built-in USB, you will need to enable flashing yourself by pulling GPIO0 low or pressing a "flash" switch.
+
+## esptool
+> A cute Python utility to communicate with the ROM bootloader in Espressif ESP8266. It is intended to be a simple, platform independent, open source replacement for XTCOM.
+
+Source: [https://github.com/themadinventor/esptool](https://github.com/themadinventor/esptool)
+
+Supported platforms: OS X, Linux, Windows, anything that runs Python
+
+**Running esptool.py**
+
+Run the following command to flash an *aggregated* binary as is produced for example by the [cloud build service](build.md#cloud-build-service) or the [Docker image](build.md#docker-image).
+
+`esptool.py --port <USB-port-with-ESP8266> write_flash 0x00000 <nodemcu-firmware>.bin`
+
+## NodeMCU Flasher
+> A firmware Flash tool for NodeMCU...We are working on next version and will use QT framework. It will be cross platform and open-source.
+
+Source: [https://github.com/nodemcu/nodemcu-flasher](https://github.com/nodemcu/nodemcu-flasher)
+
+Supported platforms: Windows

+ 51 - 0
docs/en/index.md

@@ -0,0 +1,51 @@
+# NodeMCU Documentation
+
+NodeMCU is an [eLua](http://www.eluaproject.net/) based firmware for the [ESP8266 WiFi SOC from Espressif](http://espressif.com/en/products/esp8266/). The firmware is based on the Espressif NON-OS SDK and uses a file system based on [spiffs](https://github.com/pellepl/spiffs). The code repository consists of 98.1% C-code that glues the thin Lua veneer to the SDK.
+
+The NodeMCU *firmware* is a companion project to the popular [NodeMCU dev kits](https://github.com/nodemcu/nodemcu-devkit-v1.0), ready-made open source development boards with ESP8266-12E chips.
+
+## Programming Model
+The NodeMCU programming model is similar to that of [Node.js](https://en.wikipedia.org/wiki/Node.js), only in Lua. It is asynchronous and event-driven. Many functions, therefore, have parameters for callback functions. To give you an idea what a NodeMCU program looks like study the short snippets below. For more extensive examples have a look at the `/lua_examples` folder in the repository on GitHub.
+
+```lua
+-- a simple HTTP server
+srv = net.createServer(net.TCP)
+srv:listen(80, function(conn)
+	conn:on("receive", function(conn, payload)
+		print(payload)
+		conn:send("<h1> Hello, NodeMCU.</h1>")
+	end)
+	conn:on("sent", function(conn) conn:close() end)
+end)
+```
+```lua
+-- connect to WiFi access point
+wifi.setmode(wifi.STATION)
+wifi.sta.config("SSID", "password")
+```
+
+```lua
+-- register event callbacks for WiFi events
+wifi.sta.eventMonReg(wifi.STA_CONNECTING, function(previous_state)
+	if(previous_state==wifi.STA_GOTIP) then 
+	    print("Station lost connection with access point. Attempting to reconnect...")
+	else
+	    print("STATION_CONNECTING")
+	end
+end)
+```
+
+```lua
+-- manipulate hardware like with Arduino
+pin = 1
+gpio.mode(pin, gpio.OUTPUT)
+gpio.write(pin, gpio.HIGH)
+print(gpio.read(pin))
+```
+
+## Getting Started
+1. [Build the firmeware](build.md) with the modules you need.
+1. [Flash the firmware](flash.md) to the chip.
+1. [Upload code](upload.md) to the firmware.
+
+

+ 39 - 0
docs/en/modules/adc.md

@@ -0,0 +1,39 @@
+# ADC Module
+The ADC module provides access to the in-built ADC.
+
+On the ESP8266 there is only a single-channel, which is multiplexed with the battery voltage. Depending on the setting in the "esp init data" (byte 107) one can either use the ADC to read an external voltage, or to read the system voltage, but not both.
+
+The default setting in the NodeMCU firmware can be controlled via user_config.h at compile time, by defining one of ESP_INIT_DATA_ENABLE_READVDD33, ESP_INIT_DATA_ENABLE_READADC or ESP_INIT_DATA_FIXED_VDD33_VALUE. To change the setting at a later date, use Espressif's flash download tool to create a new init data block.
+
+## adc.read()
+
+Samples the ADC.
+
+####Syntax
+`adc.read(channel)`
+
+####Parameters
+`channel` always 0 on the ESP8266
+
+####Returns
+the sampled value (number)
+
+####Example
+```lua
+val = adc.read(0)
+```
+
+## adc.readvdd33()
+
+Reads the system voltage.
+
+####Syntax
+`adc.readvdd33()`
+
+####Parameters
+none
+
+####Returns
+system voltage in millivolts (number)
+
+If the ESP8266 has been configured to use the ADC for sampling the external pin, this function will always return 65535. This is a hardware and/or SDK limitation.

+ 170 - 0
docs/en/modules/bit.md

@@ -0,0 +1,170 @@
+# bit Module
+
+Bit manipulation support, on 32bit integers.
+
+## bit.arshift()
+Arithmetic right shift a number equivalent to `value >> shift` in C.
+
+####Syntax
+`bit.arshift(value, shift)`
+
+####Parameters
+- `value` the value to shift
+- `shift` positions to shift
+
+####Returns
+the number shifted right (arithmetically)
+
+## bit.band()
+
+Bitwise AND, equivalent to `val1 & val2 & ... & valn` in C.
+
+####Syntax
+`bit.band(val1, val2 [, ... valn])`
+
+####Parameters
+ - `val1` first AND argument
+ - `val2` second AND argument
+ - `...valn` ...nth AND argument
+
+####Returns
+the bitwise AND of all the arguments (number)
+
+## bit.bit()
+
+Generate a number with a 1 bit (used for mask generation). Equivalent to `1 << position` in C.
+
+####Syntax
+`bit.bit(position)`
+
+####Parameters
+`position` position of the bit that will be set to 1
+
+####Returns
+a number with only one 1 bit at position (the rest are set to 0)
+
+## bit.bnot()
+
+Bitwise negation, equivalent to `~value in C.
+
+####Syntax
+`bit.bnot(value)`
+
+####Parameters
+`value` the number to negate
+
+####Returns
+the bitwise negated value of the number
+
+## bit.bor()
+Bitwise OR, equivalent to `val1 | val2 | ... | valn` in C.
+
+####Syntax
+`bit.bor(val1, val2 [, ... valn])`
+
+####Parameters
+- `val1` first OR argument.
+- `val2` second OR argument.
+- `...valn` ...nth OR argument
+
+####Returns
+the bitwise OR of all the arguments (number)
+
+## bit.bxor()
+
+Bitwise XOR, equivalent to `val1 ^ val2 ^ ... ^ valn` in C.
+
+####Syntax
+`bit.bxor(val1, val2 [, ... valn])`
+
+####Parameters
+- `val1` first XOR argument
+- `val2` second XOR argument
+- `...valn` ...nth XOR argument
+
+####Returns
+the bitwise XOR of all the arguments (number)
+
+## bit.clear()
+Clear bits in a number.
+
+####Syntax
+`bit.clear(value, pos1 [, ... posn])`
+
+####Parameters
+- `value` the base number
+- `pos1` position of the first bit to clear
+- `...posn` position of thet nth bit to clear
+
+####Returns
+the number with the bit(s) cleared in the given position(s)
+
+## bit.isclear()
+
+Test if a given bit is cleared.
+
+####Syntax
+`bit.isclear(value, position)`
+
+####Parameters
+- `value` the value to test
+- `position` bit position to test
+
+####Returns
+true if the bit at the given position is 0, false othewise
+
+## bit.isset()
+
+Test if a given bit is set.
+
+####Syntax
+`bit.isset(value, position)`
+
+####Parameters
+- `value` the value to test
+- `position` bit position to test
+
+####Returns
+true if the bit at the given position is 1, false otherwise
+
+## bit.lshift()
+Left-shift a number, equivalent to `value << shift` in C.
+
+####Syntax
+`bit.lshift(value, shift)`
+
+####Parameters
+- `value` the value to shift
+- `shift` positions to shift
+
+####Returns
+the number shifted left
+
+## bit.rshift()
+
+Logical right shift a number, equivalent to `( unsigned )value >> shift` in C.
+
+####Syntax
+`bit.rshift(value, shift)`
+
+####Parameters
+- `value` the value to shift.
+- `shift` positions to shift.
+
+####Returns
+the number shifted right (logically)
+
+## bit.set()
+
+Set bits in a number.
+
+####Syntax
+`bit.set(value, pos1 [, ... posn ])`
+
+####Parameters
+- `value` the base number.
+- `pos1` position of the first bit to set.
+- `...posn` position of the nth bit to set.
+
+####Returns
+the number with the bit(s) set in the given position(s)

+ 67 - 0
docs/en/modules/bmp085.md

@@ -0,0 +1,67 @@
+# BMP085 Module
+
+This module provides access to the [BMP085](https://www.sparkfun.com/tutorials/253) temperature and pressure sensor. The module also works with BMP180.
+
+## bmp085.init()
+Initializes the module and sets the pin configuration.
+
+#### Syntax
+`bmp085.init(sda, scl)`
+
+#### Parameters
+- `sda` data pin
+- `scl` clock pin
+
+#### Returns
+`nil`
+
+## bmp085.temperature()
+Samples the sensor and returns the temperature in celsius as an integer multiplied with 10.
+
+#### Syntax
+`bmp085.temperature()`
+
+#### Returns
+temperature multiplied with 10 (integer)
+
+#### Example
+```lua
+bmp085.init(1, 2)
+local t = bmp085.temperature()
+print(string.format("Temperature: %s.%s degrees C", t / 10, t % 10))
+```
+
+## bmp085.pressure()
+Samples the sensor and returns the pressure in pascal as an integer.
+
+The optional `oversampling_setting` parameter determines for how long time the sensor samples data.
+The default is `3` which is the longest sampling setting. Possible values are 0, 1, 2, 3.
+See the data sheet for more information.
+
+#### Syntax
+`bmp085.pressure(oversampling_setting)`
+
+#### Parameters
+`oversampling_setting` integer that can be 0, 1, 2 or 3
+
+#### Returns
+pressure in pascals (integer)
+
+#### Example
+```lua
+bmp085.init(1, 2)
+local p = bmp085.pressure()
+print(string.format("Pressure: %s.%s mbar", p / 100, p % 100))
+```
+
+## bmp085.pressure_raw()
+Samples the sensor and returns the raw pressure in internal units. Might be useful if you need higher precision.
+
+#### Syntax
+`bmp085.pressure_raw(oversampling_setting)`
+
+#### Parameters
+`oversampling_setting` integer that can be 0, 1, 2 or 3
+
+#### Returns
+raw pressure sampling value (integer)

+ 49 - 0
docs/en/modules/cjson.md

@@ -0,0 +1,49 @@
+# CJSON Module
+
+The JSON support module. Allows encoding and decoding to/from JSON.
+
+Please note that nested tables can require a lot of memory to encode. To catch out-of-memory errors, use `pcall()`.
+
+## cjson.encode()
+
+Encode a Lua table to a JSON string. For details see the [documentation of the original Lua library](http://kyne.com.au/~mark/software/lua-cjson-manual.html#encode).
+
+####Syntax
+`cjson.encode(table)`
+
+####Parameters
+`table` data to encode
+
+While it also is possible to encode plain strings and numbers rather than a table, it is not particularly useful to do so.
+
+####Returns
+JSON string
+
+####Example
+```lua
+ok, json = pcall(cjson.encode, {key="value"})
+if ok then
+  print(json)
+else
+  print("failed to encode!")
+end
+```
+
+## cjson.decode()
+
+Decode a JSON string to a Lua table. For details see the [documentation of the original Lua library](http://kyne.com.au/~mark/software/lua-cjson-manual.html#_decode).
+
+####Syntax
+`cjson.decode(str)`
+
+####Parameters
+`str` JSON string to decode
+
+####Returns
+Lua table representation of the JSON data
+
+####Example
+```lua
+t = cjson.decode('{"key":"value"}')
+for k,v in pairs(t) do print(k,v) end
+```

+ 224 - 0
docs/en/modules/coap.md

@@ -0,0 +1,224 @@
+# CoAP Module
+The CoAP module provides a simple implementation according to [CoAP](http://tools.ietf.org/html/rfc7252) protocol.
+The basic endpoint server part is based on [microcoap](https://github.com/1248/microcoap), and many other code reference [libcoap](https://github.com/obgm/libcoap).
+
+This module implements both the client and the server side. GET/PUT/POST/DELETE is partially supported by the client. Server can register Lua functions and varibles. No observe or discover supported yet.
+
+## Caution
+This module is only in the very early stage and not complete yet.
+
+## Constants
+Constants for various functions.
+
+`coap.CON`, `coap.NON` represent the request types.
+
+`coap.TEXT_PLAIN`, `coap.LINKFORMAT`, `coap.XML`, `coap.OCTET_STREAM`, `coap.EXI`, `coap.JSON` represent content types.
+
+## coap.Client()
+
+Creates a CoAP client.
+
+#### Syntax
+`coap.Client()`
+
+#### Parameters
+none
+
+#### Returns
+CoAP client
+
+#### Example
+```lua
+cc = coap.Client()
+-- assume there is a coap server at ip 192.168.100
+cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
+-- GET is not complete, the result/payload only print out in console.
+cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello")
+```
+
+## coap.Server()
+
+Creates a CoAP server.
+
+#### Syntax
+`coap.Server()`
+
+#### Parameters
+none
+
+#### Returns
+CoAP server
+
+#### Example
+```lua
+-- use copper addon for firefox
+cs=coap.Server()
+cs:listen(5683)
+
+myvar=1
+cs:var("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of myvar: 1
+
+all='[1,2,3]'
+cs:var("all", coap.JSON) -- sets content type to json
+
+-- function should tack one string, return one string.
+function myfun(payload)
+  print("myfun called")
+  respond = "hello"
+  return respond
+end
+cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
+
+```
+
+# CoAP Client
+
+## coap.client:get()
+
+Issues a GET request to the server.
+
+#### Syntax
+`coap.client:get(type, uri[, payload])`
+
+#### Parameters
+- `type` `coap.CON`, `coap.NON`, defaults to CON. If the type is CON and request fails, the library retries four more times before giving up.
+- `uri` the URI such as "coap://192.168.18.103:5683/v1/v/myvar", only IP addresses are supported i.e. no hostname resoltion.
+- `payload` optional, the payload will be put in the payload section of the request.
+
+#### Returns
+`nil`
+
+## coap.client:put()
+
+Issues a PUT request to the server.
+
+#### Syntax
+`coap.client:put(type, uri[, payload])`
+
+#### Parameters
+- `type` `coap.CON`, `coap.NON`, defaults to CON. If the type is CON and request fails, the library retries four more times before giving up.
+- `uri` the URI such as "coap://192.168.18.103:5683/v1/v/myvar", only IP addresses are supported i.e. no hostname resoltion.
+- `payload` optional, the payload will be put in the payload section of the request.
+
+#### Returns
+`nil`
+
+## coap.client:post()
+
+Issues a POST request to the server.
+
+#### Syntax
+`coap.client:post(type, uri[, payload])`
+
+#### Parameters
+- `type` coap.CON, coap.NON, defaults to CON. when type is CON, and request failed, the request will retry another 4 times before giving up.
+- `uri` the uri such as coap://192.168.18.103:5683/v1/v/myvar, only IP is supported.
+- `payload` optional, the payload will be put in the payload section of the request.
+
+#### Returns
+`nil`
+
+## coap.client:delete()
+
+Issues a DELETE request to the server.
+
+#### Syntax
+`coap.client:delete(type, uri[, payload])`
+
+#### Parameters
+- `type` `coap.CON`, `coap.NON`, defaults to CON. If the type is CON and request fails, the library retries four more times before giving up.
+- `uri` the URI such as "coap://192.168.18.103:5683/v1/v/myvar", only IP addresses are supported i.e. no hostname resoltion.
+- `payload` optional, the payload will be put in the payload section of the request.
+
+#### Returns
+`nil`
+
+# CoAP Server
+
+## coap.server:listen()
+
+Starts the CoAP server on the given port.
+
+#### Syntax
+`coap.server:listen(port[, ip])`
+
+#### Parameters
+- `port` server port (number)
+- `ip` optional IP address
+
+#### Returns
+`nil`
+
+## coap.server:close()
+
+Closes the CoAP server.
+
+#### Syntax
+`coap.server:close()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+## coap.server:var()
+
+Registers a Lua variable as an endpoint in the server. the variable value then can be retrieved by a client via GET method, represented as an [URI](http://tools.ietf.org/html/rfc7252#section-6) to the client. The endpoint path for varialble is '/v1/v/'.
+
+#### Syntax
+`coap.server:var(name[, content_type])`
+
+#### Parameters
+- `name` the Lua variable's name
+- `content_type` optional, defaults to `coap.TEXT_PLAIN`, see [Content Negotiation](http://tools.ietf.org/html/rfc7252#section-5.5.4)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- use copper addon for firefox
+cs=coap.Server()
+cs:listen(5683)
+
+myvar=1
+cs:var("myvar") -- get coap://192.168.18.103:5683/v1/v/myvar will return the value of myvar: 1
+-- cs:var(myvar), WRONG, this api accept the name string of the varialbe. but not the variable itself.
+all='[1,2,3]'
+cs:var("all", coap.JSON) -- sets content type to json
+```
+
+## coap.server:func()
+
+Registers a Lua function as an endpoint in the server. The function then can be called by a client via POST method. represented as an [URI](http://tools.ietf.org/html/rfc7252#section-6) to the client. The endpoint path for function is '/v1/f/'. 
+
+When the client issues a POST request to this URI, the payload will be passed to the function as parameter. The function's return value will be the payload in the message to the client.
+
+The function registered SHOULD accept ONLY ONE string type parameter, and return ONE string value or return nothing.
+
+#### Syntax
+`coap.server:func(name[, content_type])`
+
+#### Parameters
+- `name` the Lua function's name
+- `content_type` optional, defaults to `coap.TEXT_PLAIN`, see [Content Negotiation](http://tools.ietf.org/html/rfc7252#section-5.5.4)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- use copper addon for firefox
+cs=coap.Server()
+cs:listen(5683)
+
+-- function should take only one string, return one string.
+function myfun(payload)
+  print("myfun called")
+  respond = "hello"
+  return respond
+end
+cs:func("myfun") -- post coap://192.168.18.103:5683/v1/f/myfun will call myfun
+-- cs:func(myfun), WRONG, this api accept the name string of the function. but not the function itself.
+```

+ 110 - 0
docs/en/modules/crypto.md

@@ -0,0 +1,110 @@
+# crypto Module
+
+The crypto modules provides various functions for working with cryptographic algorithms.
+
+## crypto.hash()
+
+Compute a cryptographic hash of a Lua string.
+
+#### Syntax
+`hash = crypto.hash(algo, str)`
+
+#### Parameters
+`algo` the hash algorithm to use, case insensitive string
+
+Supported hash algorithms are:
+
+- MD2 (not available by default, has to be explicitly enabled in `app/include/user_config.h`)
+- MD5
+- SHA1
+- SHA256, SHA384, SHA512 (unless disabled in `app/include/user_config.h`)
+
+#### Returns
+A binary string containing the message digest. To obtain the textual version (ASCII hex characters), please use [`crypto.toHex()`](#cryptotohex	).
+
+#### Example
+```lua
+print(crypto.toHex(crypto.hash("sha1","abc")))
+```
+
+## crypto.hmac()
+
+Compute a [HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code) (Hashed Message Authentication Code) signature for a Lua string.
+
+#### Syntax
+`signature = crypto.hmac(algo, str, key)`
+
+#### Parameters
+- `algo` hash algorithm to use, case insensitive string
+- `str` data to calculate the hash for
+- `key` key to use for signing, may be a binary string
+
+Supported hash algorithms are:
+
+- MD2 (not available by default, has to be explicitly enabled in `app/include/user_config.h`)
+- MD5
+- SHA1
+- SHA256, SHA384, SHA512 (unless disabled in `app/include/user_config.h`)
+
+#### Returns
+A binary string containing the HMAC signature. Use [`crypto.toHex()`](#cryptotohex	) to obtain the textual version.
+
+#### Example
+```lua
+print(crypto.toHex(crypto.hmac("sha1","abc","mysecret")))
+```
+
+## crypto.mask()
+
+Applies an XOR mask to a Lua string. Note that this is not a proper cryptographic mechanism, but some protocols may use it nevertheless.
+
+#### Syntax
+`crypto.mask(message, mask)`
+
+#### Parameters
+- `message` message to mask
+- `mask` the mask to apply, repeated if shorter than the message
+
+#### Returns
+The masked message, as a binary string. Use [`crypto.toHex()`](#cryptotohex) to get a textual representation of it.
+
+#### Example
+```lua
+print(crypto.toHex(crypto.mask("some message to obscure","X0Y7")))
+```
+
+## crypto.toBase64()
+
+Provides a Base64 representation of a (binary) Lua string.
+
+#### Syntax
+`b64 = crypto.toBase64(binary)`
+
+#### Parameters
+`binary` input string to Base64 encode
+
+#### Return
+A Base64 encoded string.
+
+#### Example
+```lua
+print(crypto.toBase64(crypto.hash("sha1","abc")))
+```
+
+## crypto.toHex()
+
+Provides an ASCII hex representation of a (binary) Lua string. Each byte in the input string is represented as two hex characters in the output.
+
+#### Syntax
+`hexstr = crypto.toHex(binary)`
+
+#### Parameters
+`binary` input string to get hex representation for
+
+#### Returns
+An ASCII hex string.
+
+#### Example
+```lua
+print(crypto.toHex(crypto.hash("sha1","abc")))
+```

+ 93 - 0
docs/en/modules/dht.md

@@ -0,0 +1,93 @@
+# dht Module
+
+## Constants
+`dht.OK` (0), `dht.ERROR_CHECKSUM` (1), `dht.ERROR_TIMEOUT` (2)
+
+## dht.read()
+Read all kinds of DHT sensors, including DHT11, 21, 22, 33, 44 humidity temperature combo sensor.
+
+#### Syntax
+`dht.read(pin)`
+
+#### Parameters
+`pin` pin number of DHT sensor (can't be 0), type is number
+
+#### Returns
+- `status` as defined in Constants
+- `temp` temperature (see note below)
+- `humi` humidity (see note below)
+- `temp_dec` temperature decimal
+- `humi_dec` humidity decimal
+
+!!! note "Note:"
+
+    If using float firmware then `temp` and `humi` are floating point numbers. On an integer firmware, the final values have to be concatenated from `temp` and `temp_dec` / `humi` and `hum_dec`.
+
+#### Example
+```lua
+pin = 5
+status, temp, humi, temp_dec, humi_dec = dht.read(pin)
+if status == dht.OK then
+    -- Integer firmware using this example
+    print(string.format("DHT Temperature:%d.%03d;Humidity:%d.%03d\r\n",
+          math.floor(temp),
+          temp_deci,
+          math.floor(humi),
+          humi_deci
+    ))
+
+    -- Float firmware using this example
+    print("DHT Temperature:"..temp..";".."Humidity:"..humi)
+
+elseif status == dht.ERROR_CHECKSUM then
+    print( "DHT Checksum error." )
+elseif status == dht.ERROR_TIMEOUT then
+    print( "DHT timed out." )
+end
+```
+
+## dht.read11()
+Read DHT11 humidity temperature combo sensor.
+
+#### Syntax
+`dht.read11(pin)`
+
+#### Parameters
+`pin` pin number of DHT11 sensor (can't be 0), type is number
+
+#### Returns
+- `status` as defined in Constants
+- `temp` temperature (see note below)
+- `humi` humidity (see note below)
+- `temp_dec` temperature decimal
+- `humi_dec` humidity decimal
+
+!!! note "Note:"
+
+    If using float firmware then `temp` and `humi` are floating point numbers. On an integer firmware, the final values have to be concatenated from `temp` and `temp_dec` / `humi` and `hum_dec`.
+
+#### See also
+[dht.read()](#dhtread)
+
+## dht.readxx()
+Read all kinds of DHT sensors, except DHT11.
+
+####Syntax
+`dht.readxx(pin)`
+
+#### Parameters
+`pin` pin number of DHT sensor (can't be 0), type is number
+
+#### Returns
+- `status` as defined in Constants
+- `temp` temperature (see note below)
+- `humi` humidity (see note below)
+- `temp_dec` temperature decimal
+- `humi_dec` humidity decimal
+
+!!! note "Note:"
+
+    If using float firmware then `temp` and `humi` are floating point numbers. On an integer firmware, the final values have to be concatenated from `temp` and `temp_dec` / `humi` and `hum_dec`.
+
+#### See also
+[dht.read()](#dhtread)

+ 47 - 0
docs/en/modules/enduser-setup.md

@@ -0,0 +1,47 @@
+# enduser setup Module
+This module provides a simple way of configuring ESP8266 chips without using a serial interface or pre-programming WiFi credentials onto the chip.
+
+![enduser setup config dialog](../../img/enduser-setup.jpg "enduser setup config dialog")
+
+After running [`enduser_setup.start()`](#enduser_setupstart) a portal like the above can be accessed through a wireless network called SetupGadget_XXXXXX. The portal is used to submit the credentials for the WiFi of the enduser.
+After an IP address has been successfully obtained this module will stop as if [`enduser_setup.stop()`](#enduser_setupstop) had been called.
+
+## enduser_setup.start()
+
+Starts the captive portal.
+
+#### Syntax
+`enduser_setup.start([onConfigured()], [onError(err_num, string)], [onDebug(string)])`
+
+#### Parameters
+ - `onConfigured()` callback will be fired when an IP-address has been obtained, just before the enduser_setup module will terminate itself
+ - `onError()` callback will be fired if an error is encountered. `err_num` is a number describing the error, and `string` contains a description of the error.
+ - `onDebug()` callback is disabled by default. It is intended to be used to find internal issues in the module. `string` contains a description of what is going on.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+enduser_setup.start(
+  function()
+    print("Connected to wifi as:" .. wifi.sta.getip())
+  end,
+  function(err, str)
+    print("enduser_setup: Err #" .. err .. ": " .. str)
+  end
+);
+```
+
+## enduser_setup.stop()
+
+Stops the captive portal.
+
+#### Syntax
+`enduser_setup.stop()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`

+ 331 - 0
docs/en/modules/file.md

@@ -0,0 +1,331 @@
+# file Module
+The file module provides access to the file system and its individual files.
+
+The file system is a flat file system, with no notion of directories/folders.
+
+Only one file can be open at any given time.
+
+## file.close()
+
+Closes the open file, if any.
+
+#### Syntax
+`file.close()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- open 'init.lua', print the first line.
+file.open("init.lua", "r")
+print(file.readline())
+file.close()
+```
+#### See also
+[`file.open()`](#fileopen)
+
+## file.flush()
+
+Flushes any pending writes to the file system, ensuring no data is lost on a restart. Closing the open file using [`file.close()`](#fileclose) performs an implicit flush as well.
+
+#### Syntax
+`file.flush()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- open 'init.lua' in 'a+' mode
+file.open("init.lua", "a+")
+-- write 'foo bar' to the end of the file
+file.write('foo bar')
+file.flush()
+-- write 'baz' too
+file.write('baz')
+file.close()
+```
+#### See also
+[`file.close()`](#fileclose)
+
+## file.format()
+
+Format the file system. Completely erases any existing file system and writes a new one. Depending on the size of the flash chip in the ESP, this may take several seconds.
+
+#### Syntax
+`file.format()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### See also
+[`file.remove()`](#fileremove)
+
+## file.fsinfo()
+
+Return size information for the file system, in bytes.
+
+#### Syntax
+`file.fsinfo()`
+
+#### Parameters
+none
+
+#### Returns
+- `remaining` (number)
+- `used`      (number)
+- `total`     (number)
+
+#### Example
+
+```lua
+-- get file system info
+remaining, used, total=file.fsinfo()
+print("\nFile system info:\nTotal : "..total.." Bytes\nUsed : "..used.." Bytes\nRemain: "..remaining.." Bytes\n")
+```
+
+## file.list()
+
+Lists all files in the file system.
+
+#### Syntax
+`file.list()`
+
+#### Parameters
+none
+
+#### Returns
+a lua table which contains the {file name: file size} pairs
+
+#### Example
+```lua
+l = file.list();
+for k,v in pairs(l) do
+  print("name:"..k..", size:"..v)
+end
+```
+
+## file.open()
+
+Opens a file for access, potentially creating it (for write modes).
+
+When done with the file, it must be closed using `file.close()`.
+
+#### Syntax
+`file.open(filename, mode)`
+
+#### Parameters
+- `filename` file to be opened, directories are not supported
+- `mode`:
+    - "r": read mode (the default)
+    - "w": write mode
+    - "a": append mode
+    - "r+": update mode, all previous data is preserved
+    - "w+": update mode, all previous data is erased
+    - "a+": append update mode, previous data is preserved, writing is only allowed at the end of file
+
+#### Returns
+`nil` if file not opened, or not exists (read modes).  `true` if file opened ok.
+
+#### Example
+```lua
+-- open 'init.lua', print the first line.
+file.open("init.lua", "r")
+print(file.readline())
+file.close()
+```
+#### See also
+- [`file.close()`](#fileclose)
+- [`file.readline()`](#filereadline)
+
+## file.read()
+
+Read content from the open file.
+
+#### Syntax
+`file.read([n_or_str])`
+
+#### Parameters
+- `n_or_str`:
+	- if nothing passed in, read all byte in file
+	- if pass a number n, then read n bytes from file, or EOF is reached
+	- if pass a string "str", then read until 'str' or EOF is reached
+
+#### Returns
+fdile content in string, or nil when EOF
+
+#### Example
+```lua
+-- print the first line of 'init.lua'
+file.open("init.lua", "r")
+print(file.read('\n'))
+file.close()
+
+-- print the first 5 byte of 'init.lua'
+file.open("init.lua", "r")
+print(file.read(5))
+file.close()
+```
+
+#### See also
+- [`file.open()`](#fileopen)
+- [`file.readline()`](#filereadline)
+
+## file.readline()
+
+Read the next line from the open file.
+
+#### Syntax
+`file.readline()`
+
+#### Parameters
+none
+
+#### Returns
+File content in string, line by line, include EOL('\n'). Return `nil` when EOF.
+
+#### Example
+```lua
+-- print the first line of 'init.lua'
+file.open("init.lua", "r")
+print(file.readline())
+file.close()
+```
+#### See also
+- [`file.open()`](#fileopen)
+- [`file.close()`](#fileclose)
+- [`file.read()`](#filereade)
+
+## file.remove()
+
+Remove a file from the file system. The file must not be currently open.
+
+###Syntax
+`file.remove(filename)`
+
+#### Parameters
+`filename` file to remove
+
+#### Returns
+`nil`
+
+#### Example
+
+```lua
+-- remove "foo.lua" from file system.
+file.remove("foo.lua")
+```
+#### See also
+[`file.open()`](#fileopen)
+
+## file.rename()
+
+Renames a file. If a file is currently open, it will be closed first.
+
+#### Syntax
+`file.rename(oldname, newname)`
+
+#### Parameters
+- `oldname` old file name
+- `newname` new file name
+
+#### Returns
+`true` on success, `false` on error.
+
+#### Example
+
+```lua
+-- rename file 'temp.lua' to 'init.lua'.
+file.rename("temp.lua","init.lua")
+```
+
+## file.seek()
+Sets and gets the file position, measured from the beginning of the file, to the position given by offset plus a base specified by the string whence.
+
+#### Syntax
+`file.seek([whence [, offset]])`
+
+#### Parameters
+- `whence`
+	- "set": base is position 0 (beginning of the file)
+	- "cur": base is current position (default value)
+	- "end": base is end of file
+- `offset` default 0
+
+If no parameters are given, the function simply returns the current file offset.
+
+#### Returns
+the resulting file position, or `nil` on error
+
+#### Example
+```lua
+file.open("init.lua", "r")
+-- skip the first 5 bytes of the file
+file.seek("set", 5)
+print(file.readline())
+file.close()
+```
+#### See also
+[`file.open()`](#fileopen)
+
+## file.write()
+
+Write a string to the open file.
+
+#### Syntax
+`file.write(string)`
+
+#### Parameters
+`string` content to be write to file
+
+#### Returns
+`true` if the write is ok, `nil` on error
+
+#### Example
+```lua
+-- open 'init.lua' in 'a+' mode
+file.open("init.lua", "a+")
+-- write 'foo bar' to the end of the file
+file.write('foo bar')
+file.close()
+```
+
+#### See also
+- [`file.open()`](#fileopen)
+- [`file.writeline()`](#filewriteline)
+
+## file.writeline()
+
+Write a string to the open file and append '\n' at the end.
+
+#### Syntax
+`file.writeline(string)`
+
+#### Parameters
+`string` content to be write to file
+
+#### Returns
+`true` if write ok, `nil` on error
+
+#### Example
+```lua
+-- open 'init.lua' in 'a+' mode
+file.open("init.lua", "a+")
+-- write 'foo bar' to the end of the file
+file.writeline('foo bar')
+file.close()
+```
+
+#### See also
+- [`file.open()`](#fileopen)
+- [`file.readline()`](#filereadline)

+ 157 - 0
docs/en/modules/gpio.md

@@ -0,0 +1,157 @@
+# GPIO Module
+
+This module provides access to the [GPIO](https://en.wikipedia.org/wiki/General-purpose_input/output) (General Purpose Input/Output) subsystem.
+
+All access is based on the I/O index number on the NodeMCU dev kits, not the internal GPIO pin. For example, the D0 pin on the dev kit is mapped to the internal GPIO pin 16.
+
+If not using a NodeMCU dev kit, please refer to the below GPIO pin maps for the index↔gpio mapping.
+
+| IO index | ESP8266 pin | IO index | ESP8266 pin |
+|---------:|:------------|---------:|:------------|
+|    0 [*] | GPIO16      |        7 | GPIO13      |
+|        1 | GPIO5       |        8 | GPIO15      |
+|        2 | GPIO4       |        9 | GPIO3       |
+|        3 | GPIO0       |       10 | GPIO1       |
+|        4 | GPIO2       |       11 | GPIO9       |
+|        5 | GPIO14      |       12 | GPIO10      |
+|        6 | GPIO12      |          |             |
+
+** [*] D0(GPIO16) can only be used as gpio read/write. No interrupt support. No pwm/i2c/ow support. **
+
+
+## gpio.mode()
+
+Initialize pin to GPIO mode, set the pin in/out direction, and optional internal pullup.
+
+#### Syntax
+`gpio.mode(pin, mode [, pullup])`
+
+#### Parameters
+- `pin` pin to configure, IO index
+- `mode` one of gpio.OUTPUT or gpio.INPUT, or gpio.INT(interrupt mode)
+- `pullup` gpio.PULLUP or gpio.FLOAT; default is gpio.FLOAT
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+gpio.mode(0, gpio.OUTPUT)
+```
+#### See also
+- [`gpio.read()`](#gpioread)
+- [`gpio.write()`](#gpiowrite)
+
+## gpio.read()
+
+Read digital GPIO pin value.
+
+#### Syntax
+`gpio.read(pin)`
+
+#### Parameters
+`pin` pin to read, IO index
+
+#### Returns
+a number, 0 = low, 1 = high
+
+#### Example
+```lua
+-- read value of gpio 0.
+gpio.read(0)
+```
+#### See also
+[`gpio.mode()`](#gpiomode)
+
+## gpio.serout()
+
+Serialize output based on a sequence of delay-times. After each delay, the pin is toggled.
+
+#### Syntax
+`gpio.serout(pin, start_level, delay_times [, repeat_num])`
+
+#### Parameters
+- `pin`  pin to use, IO index
+- `start_level` level to start on, either `gpio.HIGH` or `gpio.LOW`
+- `delay_times` an array of delay times between each toggle of the gpio pin.
+- `repeat_num` an optional number of times to run through the sequence.
+
+Note that this function blocks, and as such any use of it must adhere to the SDK guidelines of time spent blocking the stack (10-100ms). Failure to do so may lead to WiFi issues or outright crashes/reboots.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
+gpio.serout(1,1,{30,30,60,60,30,30})  -- serial one byte, b10110010
+gpio.serout(1,1,{30,70},8)  -- serial 30% pwm 10k, lasts 8 cycles
+gpio.serout(1,1,{3,7},8)  -- serial 30% pwm 100k, lasts 8 cycles
+gpio.serout(1,1,{0,0},8)  -- serial 50% pwm as fast as possible, lasts 8 cycles
+gpio.serout(1,0,{20,10,10,20,10,10,10,100}) -- sim uart one byte 0x5A at about 100kbps
+gpio.serout(1,1,{8,18},8) -- serial 30% pwm 38k, lasts 8 cycles
+```
+
+## gpio.trig()
+
+Establish a callback function to run on interrupt for a pin.
+
+There is currently no support for unregistering the callback.
+
+This function is not available if GPIO_INTERRUPT_ENABLE was undefined at compile time.
+
+#### Syntax
+`gpio.trig(pin, type [, function(level)])`
+
+#### Parameters
+- `pin` **1~12**, IO index, pin D0 does not support interrupt.
+- `type` "up", "down", "both", "low", "high", which represent rising edge, falling edge, both edge, low level, high level trig mode correspondingly.
+- `function(level)` callback function when triggered. The gpio level is the param. Use previous callback function if undefined here.
+
+#### Returns
+`nil`
+
+#### Example
+
+```lua
+-- use pin 1 as the input pulse width counter
+pin = 1
+pulse1 = 0
+du = 0
+gpio.mode(pin,gpio.INT)
+function pin1cb(level)
+  du = tmr.now() - pulse1
+  print(du)
+  pulse1 = tmr.now()
+  if level == gpio.HIGH then gpio.trig(pin, "down") else gpio.trig(pin, "up") end
+end
+gpio.trig(pin, "down", pin1cb)
+
+```
+#### See also
+[`gpio.mode()`](#gpiomode)
+
+## gpio.write ()
+
+Set digital GPIO pin value.
+
+#### Syntax
+`gpio.write(pin, level)`
+
+#### Parameters
+- `pin` pin to write, IO index
+- `level` `gpio.HIGH` or `gpio.LOW`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- set pin index 1 to GPIO mode, and set the pin to high.
+pin=1
+gpio.mode(pin, gpio.OUTPUT)
+gpio.write(pin, gpio.HIGH)
+```
+#### See also
+- [`gpio.mode()`](#gpiomode)
+- [`gpio.read()`](#gpioread)

+ 165 - 0
docs/en/modules/http.md

@@ -0,0 +1,165 @@
+# HTTP Module
+
+Basic HTTP client module.
+
+Provides an interface to do basic GET/POST/PUT/DELETE over HTTP(S), as well as customized requests. Due to the memory constraints on ESP8266, the supported page/body size is limited to 1k. Attempting to receive pages larger than this limit will fail. If larger page/body sizes are necessary, consider using `net.createConnection()` and stream in the data.
+
+Each request method takes a callback which is invoked when the response has been received from the server. The first argument is the status code, which is either a regular HTTP status code, or -1 to denote a DNS, connection or out-of-memory failure, or a timeout (currently at 10 seconds).
+
+For each operation it is also possible to include custom headers. Note that following headers *can not* be overridden however:
+  - Host
+  - Connection
+  - User-Agent
+
+The `Host` header is taken from the URL itself, the `Connection` is always set to `close`, and the `User-Agent` is `ESP8266`.
+
+Note that it is not possible to execute concurrent HTTP requests using this module. Starting a new request before the previous has completed will result in undefined behaviour.
+
+#### See also
+  - [`net.createConnection()`](#netcreateconnection)
+
+## http.delete()
+
+Executes a HTTP delete request.
+
+#### Syntax
+`http.delete(url, headers, body, callback)`
+
+#### Parameters
+  - `url` The URL to fetch, including the `http://` or `https://` prefix
+  - `headers` Optional additional headers to append, *including \r\n*; may be `nil`
+  - `body` The body to post; must already be encoded in the appropriate format, but may be empty
+  - `callback` The callback function to be invoked when the response has been received; it is invoked with the arguments `status_code` and `body`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+http.delete('https://connor.example.com/john',
+  "",
+  "",
+  function(code, data)
+    if (code < 0)
+      print("HTTP request failed")
+    else
+      print(code, data)
+    end
+  end)
+```
+
+## http.get()
+
+Executes a HTTP GET request.
+
+#### Syntax
+`http.get(url, headers, callback)`
+
+#### Parameters
+  - `url` The URL to fetch, including the `http://` or `https://` prefix
+  - `headers` Optional additional headers to append, *including \r\n*; may be `nil`
+  - `callback` The callback function to be invoked when the response has been received; it is invoked with the arguments `status_code` and `body`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+http.get("https://www.vowstar.com/nodemcu/", nil, function(code, data)
+    if (code < 0)
+      print("HTTP request failed")
+    else
+      print(code, data)
+    end
+  end)
+```
+
+## http.post()
+
+Executes a HTTP POST request.
+
+#### Syntax
+`http.post(url, headers, body, callback)`
+
+#### Parameters
+  - `url` The URL to fetch, including the `http://` or `https://` prefix
+  - `headers` Optional additional headers to append, *including \r\n*; may be `nil`
+  - `body` The body to post; must already be encoded in the appropriate format, but may be empty
+  - `callback` The callback function to be invoked when the response has been received; it is invoked with the arguments `status_code` and `body`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+http.post('http://json.example.com/something',
+  'Content-Type: application/json\r\n',
+  '{"hello":"world"}',
+  function(code, data)
+    if (code < 0)
+      print("HTTP request failed")
+    else
+      print(code, data)
+    end
+  end)
+```
+
+## http.put()
+
+Executes a HTTP PUT request.
+
+#### Syntax
+`http.put(url, headers, body, callback)`
+
+#### Parameters
+  - `url` The URL to fetch, including the `http://` or `https://` prefix
+  - `headers` Optional additional headers to append, *including \r\n*; may be `nil`
+  - `body` The body to post; must already be encoded in the appropriate format, but may be empty
+  - `callback` The callback function to be invoked when the response has been received; it is invoked with the arguments `status_code` and `body`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+http.put('http://db.example.com/items.php?key=deckard',
+  'Content-Type: text/plain\r\n',
+  'Hello!\nStay a while, and listen...\n',
+  function(code, data)
+    if (code < 0)
+      print("HTTP request failed")
+    else
+      print(code, data)
+    end
+  end)
+```
+
+## http.request()
+
+Execute a custom HTTP request for any HTTP method.
+
+#### Syntax
+`http.request(url, method, headers, body, callback)`
+
+#### Parameters
+  - `url` The URL to fetch, including the `http://` or `https://` prefix
+  - `method` The HTTP method to use, e.g. "GET", "HEAD", "OPTIONS" etc
+  - `headers` Optional additional headers to append, *including \r\n*; may be `nil`
+  - `body` The body to post; must already be encoded in the appropriate format, but may be empty
+  - `callback` The callback function to be invoked when the response has been received; it is invoked with the arguments `status_code` and `body`
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+http.request("https://www.example.com", "HEAD", "", "", function(code, data)
+  function(code, data)
+    if (code < 0)
+      print("HTTP request failed")
+    else
+      print(code, data)
+    end
+  end)
+```
+

+ 48 - 0
docs/en/modules/hx711.md

@@ -0,0 +1,48 @@
+# HX711 Module
+
+This module provides access to an [HX711 load cell amplifier/ADC](https://learn.sparkfun.com/tutorials/load-cell-amplifier-hx711-breakout-hookup-guide). The HX711 is an inexpensive 24bit ADC with programmable 128x, 64x, and 32x gain. Currently only channel A at 128x gain is supported.
+
+Note: To save ROM image space, this module is not compiled into the firmware by default.
+
+## hx711.init()
+
+Initialize io pins for hx711 clock and data.
+
+#### Syntax
+`hx711.init(clk, data)`
+
+#### Parameters
+- `clk` pin the hx711 clock signal is connected to
+- `data` pin the hx711 data signal is connected to
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- Initialize the hx711 with clk on pin 5 and data on pin 6
+hx711.init(5,6)
+```
+
+## hx711.read()
+
+Read digital loadcell ADC value.
+
+#### Syntax
+`hx711.read(mode)`
+
+#### Parameters
+`mode` ADC mode.  This parameter is currently ignored and reserved to ensure backward compatability if support for additional modes is added. Currently only channel A @ 128 gain is supported.
+
+|mode | channel | gain |
+|-----|---------|------|
+| 0   | A       | 128  |
+
+#### Returns
+a number (24 bit signed ADC value extended to the machine int size)
+
+#### Example
+```lua
+-- Read ch A with 128 gain.
+raw_data = hx711.read(0)
+```

+ 130 - 0
docs/en/modules/i2c.md

@@ -0,0 +1,130 @@
+# i2c Module
+
+## i2c.address()
+Setup I²C address and read/write mode for the next transfer.
+
+#### Syntax
+`i2c.address(id, device_addr, direction)`
+
+#### Parameters
+- `id` always 0
+- `device_addr` device address
+- `direction` `i2c.TRANSMITTER` for writing mode , `i2c. RECEIVER` for reading mode
+
+#### Returns
+`true` if ack received, `false` if no ack received.
+
+#### See also
+[i2c.read()](#i2cread)
+
+## i2c.read()
+Read data for variable number of bytes.
+
+#### Syntax
+`i2c.read(id, len)`
+
+#### Parameters
+- `id` always 0
+- `len` number of data bytes
+
+#### Returns
+`string` of received data
+
+#### Example
+```lua
+id  = 0
+sda = 1
+scl = 2
+
+-- initialize i2c, set pin1 as sda, set pin2 as scl
+i2c.setup(id, sda, scl, i2c.SLOW)
+
+-- user defined function: read from reg_addr content of dev_addr
+function read_reg(dev_addr, reg_addr)
+    i2c.start(id)
+    i2c.address(id, dev_addr, i2c.TRANSMITTER)
+    i2c.write(id, reg_addr)
+    i2c.stop(id)
+    i2c.start(id)
+    i2c.address(id, dev_addr, i2c.RECEIVER)
+    c = i2c.read(id, 1)
+    i2c.stop(id)
+    return c
+end
+
+-- get content of register 0xAA of device 0x77
+reg = read_reg(0x77, 0xAA)
+print(string.byte(reg))
+```
+
+####See also
+[i2c.write()](#i2cwrite)
+
+## i2c.setup()
+Initialize the I²C module.
+
+#### Syntax
+`i2c.setup(id, pinSDA, pinSCL, speed)`
+
+####Parameters
+- `id` always 0
+- `pinSDA` 1~12, IO index
+- `pinSCL` 1~12, IO index
+- `speed` only `i2c.SLOW` supported
+
+#### Returns
+`speed` the selected speed
+
+####See also
+[i2c.read()](#i2cread)
+
+## i2c.start()
+Send an I²C start condition.
+
+#### Syntax
+`i2c.start(id)`
+
+#### Parameters
+`id` always 0
+
+#### Returns
+`nil`
+
+####See also
+[i2c.read()](#i2cread)
+
+## i2c.stop()
+Send an I²C stop condition.
+
+#### Syntax
+`i2c.stop(id)`
+
+####Parameters
+`id` always 0
+
+#### Returns
+`nil`
+
+####See also
+[i2c.read()](#i2cread)
+
+## i2c.write()
+Write data to I²C bus. Data items can be multiple numbers, strings or lua tables.
+
+####Syntax
+`i2c.write(id, data1[, data2[, ..., datan]])`
+
+####Parameters
+- `id` always 0
+- `data` data can be numbers, string or lua table.
+
+#### Returns
+`number` number of bytes written
+
+#### Example
+```lua
+i2c.write(0, "hello", "world")
+```
+
+#### See also
+[i2c.read()](#i2cread)

+ 152 - 0
docs/en/modules/mqtt.md

@@ -0,0 +1,152 @@
+# MQTT Module
+
+The client adheres to version 3.1.1 of the [MQTT](https://en.wikipedia.org/wiki/MQTT) protocol. Make sure that your broker supports and is correctly configured for version 3.1.1. The client is backwards incompatible with brokers running MQTT 3.1.
+
+## mqtt.Client()
+
+Creates a MQTT client.
+
+#### Syntax
+`mqtt.Client(clientid, keepalive, username, password[, cleansession])`
+
+#### Parameters
+- `clientid` client ID
+- `keepalive` keepalive seconds
+- `username` user name
+- `password` user password
+- `cleansession` 0/1 for `false`/`true`
+
+#### Returns
+MQTT client
+
+#### Example
+```lua
+-- init mqtt client with keepalive timer 120sec
+m = mqtt.Client("clientid", 120, "user", "password")
+
+-- setup Last Will and Testament (optional)
+-- Broker will publish a message with qos = 0, retain = 0, data = "offline" 
+-- to topic "/lwt" if client don't send keepalive packet
+m:lwt("/lwt", "offline", 0, 0)
+
+m:on("connect", function(client) print ("connected") end)
+m:on("offline", function(client) print ("offline") end)
+
+-- on publish message receive event
+m:on("message", function(client, topic, data) 
+  print(topic .. ":" ) 
+  if data ~= nil then
+    print(data)
+  end
+end)
+
+-- for TLS: m:connect("192.168.11.118", secure-port, 1)
+m:connect("192.168.11.118", 1880, 0, function(client) print("connected") end)
+
+-- Calling subscribe/publish only makes sense once the connection
+-- was successfully established. In a real-world application you want
+-- move those into the 'connect' callback or make otherwise sure the 
+-- connection was established.
+
+-- subscribe topic with qos = 0
+m:subscribe("/topic",0, function(client) print("subscribe success") end)
+-- publish a message with data = hello, QoS = 0, retain = 0
+m:publish("/topic","hello",0,0, function(client) print("sent") end)
+
+m:close();
+-- you can call m:connect again
+```
+
+# MQTT Client
+
+
+## mqtt.client:close()
+
+Closes connection to the broker.
+
+#### Syntax
+`mqtt:close()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+## mqtt.client:connect()
+
+Connects to the broker specified by the given host, port, and secure options.
+
+#### Syntax
+`mqtt:connect(host, port, secure, function(client))`
+
+#### Parameters
+- `host` host, domain or IP (string)
+- `port` broker port (number)
+- `secure` 0/1 for `false`/`true`, default 0. [As per #539](https://github.com/nodemcu/nodemcu-firmware/issues/539#issuecomment-170298120) secure connections use TLS 1.2.
+- `function(client)` call back function for when the connection was established
+
+#### Returns
+`nil`
+
+## mqtt.client:lwt()
+
+Setup [Last Will and Testament](http://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament) (optional). A broker will publish a message with qos = 0, retain = 0, data = "offline" to topic "/lwt" if client does not send keepalive packet.
+
+#### Syntax
+`mqtt:lwt(topic, message, qos, retain)`
+
+#### Parameters
+- `topic` the topic to publish to (string)
+- `message` the message to publish, (buffer or string)
+- `qos` QoS level, default 0
+- `retain` retain flag, default 0
+
+#### Returns
+`nil`
+
+## mqtt.client:on()
+
+Registers a callback function for an event.
+
+#### Syntax
+`mqtt:on(event, function(client[, topic[, message]]))`
+
+#### Parameters
+- `event` can be "connect", "message" or "offline"
+- `function(client[, topic[, message]])` callback function. The first parameter is the client. If event is "message", the 2nd and 3rd param are received topic and message (strings).
+
+#### Returns
+`nil`
+
+## mqtt.client:publish()
+
+Publishes a message.
+
+#### Syntax
+`mqtt:publish(topic, payload, qos, retain, function(client))`
+
+#### Parameters
+- `topic` the topic to publish to ([topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices))
+- `message` the message to publish, (buffer or string)
+- `qos` QoS level, default 0
+- `retain` retain flag, default 0
+- `function(client)` callback fired when PUBACK received
+
+#### Returns
+`nil`
+
+## mqtt.client:subscribe()
+
+Subscribes to one or several topics.
+
+#### Syntax
+`mqtt:subscribe(topic, qos, function(client, topic, message))`
+
+#### Parameters
+- `topic` a [topic string](http://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices)
+- `qos` QoS subscription level, default 0
+- `function(client, topic, message)` callback fired when message received
+
+#### Returns
+`nil`

+ 284 - 0
docs/en/modules/net.md

@@ -0,0 +1,284 @@
+# net Module
+
+## Constants
+`net.TCP`, `net.UDP`
+
+## net.createConnection()
+
+Creates a client.
+
+#### Syntax
+`net.createConnection(type, secure)`
+
+#### Parameters
+- `type` `net.TCP` or `net.UDP`
+- `secure` 1 for encrypted, 0 for plain
+
+#### Returns
+net.socket sub module
+
+#### Example
+
+```lua
+net.createConnection(net.UDP, 0)
+```
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+## net.createServer()
+
+Creates a server.
+
+#### Syntax
+`net.createServer(type, timeout)`
+
+#### Parameters
+- `type` `net.TCP` or `net.UDP`
+- `timeout` for a TCP server timeout is 1~28'800 seconds (for an inactive client to be disconnected)
+
+#### Returns
+net.server sub module
+
+#### Example
+
+```lua
+net.createServer(net.TCP, 30) -- 30s timeout
+```
+
+#### See also
+[`net.createConnection()`](#netcreateconnection)
+
+# net.server Module
+
+## net.server:close()
+
+Closes the server.
+
+#### Syntax
+`net.server.close()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- creates a server
+sv = net.createServer(net.TCP, 30)
+-- closes the server
+sv:close()
+```
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+## net.server:listen()
+
+Listen on port from IP address.
+
+#### Syntax
+`net.server.listen(port,[ip],function(net.socket))`
+
+#### Parameters
+- `port` port number
+- `ip` IP address string, can be omitted
+- `function(net.socket)` callback function, pass to caller function as param if a connection is created successfully
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+ -- 30s time out for a inactive client
+sv = net.createServer(net.TCP, 30)
+-- server listens on 80, if data received, print data to console and send "hello world" back to caller
+sv:listen(80, function(c)
+	c:on("receive", function(c, pl) 
+		print(pl)
+	end)
+	c:send("hello world")
+end)
+```
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+# net.socket Module
+## net.socket:close()
+
+Closes socket.
+
+#### Syntax
+`close()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+## net.socket:connect()
+
+Connect to a remote server.
+
+#### Syntax
+`connect(port, ip|domain)`
+
+#### Parameters
+- `port` port number
+- `ip` IP address or domain name string
+
+#### Returns
+`nil`
+
+#### See also
+[`net.socket:on()`](#netsocketon)
+
+## net.socket:dns()
+
+Provides DNS resolution for a hostname.
+
+#### Syntax
+`dns(domain, function(net.socket, ip))`
+
+#### Parameters
+- `domain` domain name
+- `function(net.socket, ip)` callback function. The first parameter is the socket, the second parameter is the IP address as a string.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+sk = net.createConnection(net.TCP, 0)
+sk:dns("www.nodemcu.com", function(conn, ip) print(ip) end)
+sk = nil
+```
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+## net.socket:on()
+
+Register callback functions for specific events.
+
+#### Syntax
+`on(event, function())`
+
+#### Parameters
+- `event` string, which can be "connection", "reconnection", "disconnection", "receive" or "sent"
+- `function(net.socket[, string])` callback function. The first parameter is the socket. If event is "receive", the second parameter is the received data as string.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+sk = net.createConnection(net.TCP, 0)
+sk:on("receive", function(sck, c) print(c) end )
+sk:connect(80,"192.168.0.66")
+sk:on("connection", function(sck,c)
+    -- Wait for connection before sending.
+    sk:send("GET / HTTP/1.1\r\nHost: 192.168.0.66\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
+end)
+```
+
+#### See also
+[`net.createServer()`](#netcreateserver)
+
+## net.socket:send()
+
+Sends data to server.
+
+#### Syntax
+`send(string, function(sent))`
+
+#### Parameters
+- `string` data in string which will be sent to server
+- `function(sent)` callback function for sending string
+
+#### Returns
+`nil`
+
+#### Note
+
+Multiple consecutive `send()` calls aren't guaranteed to work (and often don't) as network requests are treated as separate tasks by the SDK. Instead, subscribe to the "sent" event on the socket and send additional data (or close) in that callback. See [#730](https://github.com/nodemcu/nodemcu-firmware/issues/730#issuecomment-154241161) for an example and explanation.
+
+#### See also
+[`net.socket:on()`](#netsocketon)
+
+# net.dns Module
+
+## net.dns.getdnsserver()
+
+Gets the IP address of the DNS server used to resolve hostnames.
+
+#### Syntax
+`net.dns.getdnsserver(dns_index)`
+
+#### Parameters
+dns_index which DNS server to get (range 0~1)
+
+#### Returns
+IP address (string) of DNS server
+
+#### Example
+```lua
+print(net.dns.getdnsserver(0)) -- 208.67.222.222
+print(net.dns.getdnsserver(1)) -- nil
+
+net.dns.setdnsserver("8.8.8.8", 0)
+net.dns.setdnsserver("192.168.1.252", 1)
+
+print(net.dns.getdnsserver(0)) -- 8.8.8.8
+print(net.dns.getdnsserver(1)) -- 192.168.1.252
+```
+#### See also
+[`net.dns:setdnsserver()`](#netdnssetdnsserver)
+
+## net.dns.resolve()
+
+Resolve a hostname to an IP address. Doesn't require a socket like [`net.socket.dns()`](#netsocketdns).
+
+#### Syntax
+`net.dns.resolve(host, function(ip))`
+
+#### Parameters
+- `host` hostname to resolve
+- `function(sk, ip)` callback called when the name was resolved. Don't use `sk`, it's a socket used internally to resolve the hostname.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+net.dns.resolve("www.google.com", function(sk, ip)
+    if (ip == nil) then print("DNS fail!") else print(ip) end
+end)
+```
+#### See also
+[`net.socket:dns()`](#netsocketdns)
+
+## net.dns.setdnsserver()
+
+Sets the IP of the DNS server used to resolve hostnames. Default: resolver1.opendns.com (208.67.222.222). You can specify up to 2 DNS servers.
+
+#### Syntax
+`net.dns.setdnsserver(dns_ip_addr, dns_index)`
+
+#### Parameters
+- `dns_ip_addr` IP address of a DNS server
+- `dns_index` which DNS server to set (range 0~1). Hence, it supports max. 2 servers. 
+
+#### Returns
+`nil`
+
+#### See also
+[`net.dns:getdnsserver()`](#netdnsgetdnsserver)
+

+ 380 - 0
docs/en/modules/node.md

@@ -0,0 +1,380 @@
+# node Module
+The node module provides access to system-level features such as sleep, restart and various info and IDs.
+
+## node.bootreason()
+
+Returns the boot reason and extended reset info.
+
+The first value returned is the raw code, not the new "reset info" code which was introduced in recent SDKs. Values are:
+
+  - 1, power-on
+  - 2, reset (software?)
+  - 3, hardware reset via reset pin
+  - 4, WDT reset (watchdog timeout)
+
+The second value returned is the extended reset cause. Values are:
+
+  - 0, power-on
+  - 1, hardware watchdog reset
+  - 2, exception reset
+  - 3, software watchdog reset
+  - 4, software restart
+  - 5, wake from deep sleep
+  - 6, external reset
+
+In general, the extended reset cause supercedes the raw code. The raw code is kept for backwards compatibility only. For new applications it is highly recommended to use the extended reset cause instead.
+
+In case of extended reset cause 3 (exception reset), additional values are returned containing the crash information. These are, in order, EXCCAUSE, EPC1, EPC2, EPC3, EXCVADDR, and DEPC.
+
+#### Syntax
+`node.bootreason()`
+
+#### Parameters
+none
+
+#### Returns
+`rawcode, reason [, exccause, epc1, epc2, epc3, excvaddr, depc ]`
+
+#### Example
+```lua
+_, reset_reason = node.bootreason()
+if reset_reason == 0 then print("Power UP!") end
+```
+
+## node.chipid()
+
+Returns the ESP chip ID.
+
+#### Syntax
+`node.chipid()`
+
+#### Parameters
+none
+
+#### Returns
+chip ID (number)
+
+## node.compile()
+
+Compiles a Lua text file into Lua bytecode, and saves it as .lc file.
+
+#### Syntax
+`node.compile("file.lua")`
+
+#### Parameters
+`filename` name of Lua text file
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+file.open("hello.lua","w+")
+file.writeline([[print("hello nodemcu")]])
+file.writeline([[print(node.heap())]])
+file.close()
+
+node.compile("hello.lua")
+dofile("hello.lua")
+dofile("hello.lc")
+```
+
+## node.dsleep()
+
+Enters deep sleep mode, wakes up when timed out.
+
+The maximum sleep time is 4294967295us, ~71 minutes. This is an SDK limitation.
+Firmware from before 05 Jan 2016 have a maximum sleeptime of ~35 minutes.
+
+!!! note "Note:"
+
+    This function can only be used in the condition that esp8266 PIN32(RST) and PIN8(XPD_DCDC aka GPIO16) are connected together. Using sleep(0) will set no wake up timer, connect a GPIO to pin RST, the chip will wake up by a falling-edge on pin RST.
+
+#### Syntax
+`node.dsleep(us, option)`
+
+#### Parameters
+ - `us` number (integer) or `nil`, sleep time in micro second. If `us == 0`, it will sleep forever. If `us == nil`, will not set sleep time.
+
+ - `option` number (integer) or `nil`. If `nil`, it will use last alive setting as default option.
+	- 0, init data byte 108 is valuable
+	- \> 0, init data byte 108 is valueless
+	- 0, RF_CAL or not after deep-sleep wake up, depends on init data byte 108
+	- 1, RF_CAL after deep-sleep wake up, there will belarge current
+	- 2, no RF_CAL after deep-sleep wake up, there will only be small current
+	- 4, disable RF after deep-sleep wake up, just like modem sleep, there will be the smallest current
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+--do nothing
+node.dsleep()
+--sleep μs
+node.dsleep(1000000)
+--set sleep option, then sleep μs
+node.dsleep(1000000, 4)
+--set sleep option only
+node.dsleep(nil,4)
+```
+
+## node.flashid()
+
+Returns the flash chip ID.
+
+#### Syntax
+`node.flashid()`
+
+#### Parameters
+none
+
+#### Returns
+flash ID (number)
+
+## node.heap()
+
+Returns the current available heap size in bytes. Note that due to fragmentation, actual allocations of this size may not be possible.
+
+#### Syntax
+`node.heap()`
+
+#### Parameters
+none
+
+#### Returns
+system heap size left in bytes (number)
+
+## node.info()
+
+Returns NodeMCU version, chipid, flashid, flash size, flash mode, flash speed.
+
+#### Syntax
+`node.info()`
+
+#### Parameters
+none
+
+#### Returns
+ - `majorVer` (number)
+ - `minorVer` (number)
+ - `devVer` (number)
+ - `chipid` (number)
+ - `flashid` (number)
+ - `flashsize` (number)
+ - `flashmode` (number)
+ - `flashspeed` (number)
+
+#### Example
+```lua
+majorVer, minorVer, devVer, chipid, flashid, flashsize, flashmode, flashspeed = node.info()
+print("NodeMCU "..majorVer.."."..minorVer.."."..devVer)
+```
+
+## node.input()
+
+Submits a string to the Lua interpreter. Similar to `pcall(loadstring(str))`, but without the single-line limitation.
+
+!!! note "Note:"
+
+    This function only has an effect when invoked from a callback. Using it directly on the console **does not work**.
+
+#### Syntax
+`node.input(str)`
+
+#### Parameters
+`str` Lua chunk
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+sk:on("receive", function(conn, payload) node.input(payload) end)
+```
+
+#### See also
+[`node.output()`](#nodeoutput)
+
+## node.key() --deprecated
+
+Defines action to take on button press (on the old devkit 0.9), button connected to GPIO 16.
+
+This function is only available if the firmware was compiled with DEVKIT_VERSION_0_9 defined.
+
+#### Syntax
+`node.key(type, function())`
+
+#### Parameters
+  - `type`: type is either string "long" or "short". long: press the key for 3 seconds, short: press shortly(less than 3 seconds)
+  - `function`: user defined function which is called when key is pressed. If nil, remove the user defined function. Default function: long: change LED blinking rate,  short: reset chip
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+node.key("long", function() print('hello world') end)
+```
+#### See also
+[`node.led()`](#nodeled-deprecated)
+
+## node.led() --deprecated
+
+Sets the on/off time for the LED (on the old devkit 0.9), with the LED connected to GPIO16, multiplexed with [`node.key()`](#nodekey-deprecated).
+
+This function is only available if the firmware was compiled with DEVKIT_VERSION_0_9 defined.
+
+#### Syntax
+`node.led(low, high)`
+
+#### Parameters
+  - `low` LED off time, LED keeps on when low=0. Unit: milliseconds, time resolution: 80~100ms
+  - `high` LED on time. Unit: milliseconds, time resolution: 80~100ms
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- turn led on forever.
+node.led(0)
+```
+
+#### See also
+[`node.key()`](#nodekey-deprecated)
+
+## node.output()
+
+Redirects the Lua interpreter output to a callback function. Optionally also prints it to the serial console.
+
+!!! note "Note:"
+
+    Do **not** attempt to `print()` or otherwise induce the Lua interpreter to produce output from within the callback function. Doing so results in infinite recursion, and leads to a watchdog-triggered restart.
+
+#### Syntax
+`node.output(function(str), serial_debug)`
+
+#### Parameters
+  - `output_fn(str)` a function accept every output as str, and can send the output to a socket (or maybe a file).
+  - `serial_debug` 1 output also show in serial. 0: no serial output.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+function tonet(str)
+  sk:send(str)
+end
+node.output(tonet, 1)  -- serial also get the lua output.
+```
+
+```lua
+-- a simple telnet server
+s=net.createServer(net.TCP)
+s:listen(2323,function(c)
+   con_std = c
+   function s_output(str)
+      if(con_std~=nil)
+         then con_std:send(str)
+      end
+   end
+   node.output(s_output, 0)   -- re-direct output to function s_ouput.
+   c:on("receive",function(c,l)
+      node.input(l)           -- works like pcall(loadstring(l)) but support multiple separate line
+   end)
+   c:on("disconnection",function(c)
+      con_std = nil
+      node.output(nil)        -- un-regist the redirect output function, output goes to serial
+   end)
+end)
+```
+#### See also
+[`node.input()`](#nodeinput)
+
+## node.readvdd33() --deprecated
+Moved to [`adc.readvdd33()`](adc/#adcreadvdd33).
+
+## node.restart()
+
+Restarts the chip.
+
+#### Syntax
+`node.restart()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+## node.restore()
+
+Restores system configuration to defaults. Erases all stored WiFi settings, and resets the "esp init data" to the defaults. This function is intended as a last-resort without having to reflash the ESP altogether.
+
+This also uses the SDK function `system_restore()`, which doesn't document precisely what it erases/restores.
+
+#### Syntax
+`node.restore()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+node.restore()
+node.restart() -- ensure the restored settings take effect
+```
+
+## node.setcpufreq()
+
+Change the working CPU Frequency.
+
+#### Syntax
+`node.setcpufreq(speed)`
+
+#### Parameters
+`speed` constant 'node.CPU80MHZ' or 'node.CPU160MHZ'
+
+#### Returns
+target CPU frequency (number)
+
+#### Example
+```lua
+node.setcpufreq(node.CPU80MHZ)
+```
+
+## node.stripdebug()
+
+Controls the amount of debug information kept during [`node.compile()`](#nodecompile), and allows removal of debug information from already compiled Lua code.
+
+Only recommended for advanced users, the NodeMCU defaults are fine for almost all use cases.
+
+####Syntax
+`node.stripdebug([level[, function]])`
+
+#### Parameters
+- `level`
+	- 1, don't discard debug info
+	- 2, discard Local and Upvalue debug info
+	- 3, discard Local, Upvalue and line-number debug info
+- `function` a compiled function to be stripped per setfenv except 0 is not permitted.
+
+If no arguments are given then the current default setting is returned. If function is omitted, this is the default setting for future compiles. The function argument uses the same rules as for `setfenv()`.
+
+####  Returns
+If invoked without arguments, returns the current level settings. Otherwise, `nil` is returned.
+
+#### Example
+```lua
+node.stripdebug(3)
+node.compile('bigstuff.lua')
+```
+
+#### See also
+[`node.compile()`](#nodecompile)
+

+ 271 - 0
docs/en/modules/ow.md

@@ -0,0 +1,271 @@
+# 1-Wire Module
+
+This module provides functions to work with the [1-Wire](https://en.wikipedia.org/wiki/1-Wire) device communications bus system.
+
+## ow.check_crc16()
+Computes the 1-Wire CRC16 and compare it against the received CRC.
+
+#### Syntax
+`ow.check_crc16(buf, inverted_crc0, inverted_crc1[, crc])`
+
+#### Parameters
+  - `buf` string value, data to be calculated check sum in string
+  - `inverted_crc0` LSB of received CRC
+  - `inverted_crc1` MSB of received CRC
+  - `crc` CRC starting value (optional)
+
+#### Returns
+true if the CRC matches, false otherwise
+
+## ow.crc16()
+Computes a Dallas Semiconductor 16 bit CRC.  This is required to check the integrity of data received from many 1-Wire devices.  Note that the CRC computed here is **not** what you'll get from the 1-Wire network, for two reasons:
+
+1. The CRC is transmitted bitwise inverted.
+2. Depending on the endian-ness of your processor, the binary representation of the two-byte return value may have a different byte order than the two bytes you get from 1-Wire.
+
+#### Syntax
+`ow.crc16(buf[, crc])`
+
+#### Parameters
+- `buf` string value, data to be calculated check sum in string
+- `crc` CRC starting value (optional)
+
+#### Returns
+the CRC16 as defined by Dallas Semiconductor
+
+## ow.crc8()
+Computes a Dallas Semiconductor 8 bit CRC, these are used in the ROM and scratchpad registers.
+
+#### Syntax
+`ow.crc8(buf)`
+
+#### Parameters
+`buf` string value, data to be calculated check sum in string
+
+#### Returns
+CRC result as byte
+
+## ow.depower()
+Stops forcing power onto the bus. You only need to do this if you used the 'power' flag to `ow.write()` or used a `ow.write_bytes()` and aren't about to do another read or write.
+
+#### Syntax
+`ow.depower(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+`nil`
+
+####See also
+- [ow.write()](#owwrite)
+- [ow.write_bytes()](#owwrite_bytes)
+
+## ow.read()
+Reads a byte.
+
+####Syntax
+`ow.read(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+byte read from slave device
+
+## ow.read_bytes()
+Reads multi bytes.
+
+#### Syntax
+`ow.read_bytes(pin, size)`
+
+#### Parameters
+- `pin` 1~12, I/O index
+- `size` number of bytes to be read from slave device
+
+#### Returns
+`string` bytes read from slave device
+
+## ow.reset()
+Performs a 1-Wire reset cycle.
+
+#### Syntax
+`ow.reset(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+- `1` if a device responds with a presence pulse
+- `0` if there is no device or the bus is shorted or otherwise held low for more than 250 µS
+
+## ow.reset_search()
+Clears the search state so that it will start from the beginning again.
+
+#### Syntax
+`ow.reset_search(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+`nil`
+
+## ow.search()
+Looks for the next device.
+
+#### Syntax
+`ow.search(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+`rom_code` string with length of 8 upon success. It contains the rom code of slave device. Returns `nil` if search was unsuccessful.
+
+#### See also
+[ow.target_search()](#owtargetsearch)
+
+## ow.select()
+Issues a 1-Wire rom select command. Make sure you do the `ow.reset(pin)` first.
+
+#### Syntax
+`ow.select(pin, rom)`
+
+#### Parameters
+- `pin` 1~12, I/O index
+- `rom` string value, len 8, rom code of the salve device
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- 18b20 Example
+pin = 9
+ow.setup(pin)
+count = 0
+repeat
+  count = count + 1
+  addr = ow.reset_search(pin)
+  addr = ow.search(pin)
+  tmr.wdclr()
+until (addr ~= nil) or (count > 100)
+if addr == nil then
+  print("No more addresses.")
+else
+  print(addr:byte(1,8))
+  crc = ow.crc8(string.sub(addr,1,7))
+  if crc == addr:byte(8) then
+    if (addr:byte(1) == 0x10) or (addr:byte(1) == 0x28) then
+      print("Device is a DS18S20 family device.")
+        repeat
+          ow.reset(pin)
+          ow.select(pin, addr)
+          ow.write(pin, 0x44, 1)
+          tmr.delay(1000000)
+          present = ow.reset(pin)
+          ow.select(pin, addr)
+          ow.write(pin,0xBE,1)
+          print("P="..present)  
+          data = nil
+          data = string.char(ow.read(pin))
+          for i = 1, 8 do
+            data = data .. string.char(ow.read(pin))
+          end
+          print(data:byte(1,9))
+          crc = ow.crc8(string.sub(data,1,8))
+          print("CRC="..crc)
+          if crc == data:byte(9) then
+             t = (data:byte(1) + data:byte(2) * 256) * 625
+             t1 = t / 10000
+             t2 = t % 10000
+             print("Temperature="..t1.."."..t2.."Centigrade")
+          end                   
+          tmr.wdclr()
+        until false
+    else
+      print("Device family is not recognized.")
+    end
+  else
+    print("CRC is not valid!")
+  end
+end
+```
+
+####See also
+[ow.reset()](#owreset)
+
+## ow.setup()
+Sets a pin in onewire mode.
+
+#### Syntax
+`ow.setup(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+`nil`
+
+## ow.skip()
+Issues a 1-Wire rom skip command, to address all on bus.
+
+#### Syntax
+`ow.skip(pin)`
+
+#### Parameters
+`pin` 1~12, I/O index
+
+#### Returns
+`nil`
+
+## ow.target_search()
+Sets up the search to find the device type `family_code`. The search itself has to be initiated with a subsequent call to `ow.search()`.
+
+#### Syntax
+`ow.target_search(pin, family_code)`
+
+#### Parameters
+- `pin` 1~12, I/O index
+- `family_code` byte for family code
+
+#### Returns
+`nil`
+
+####See also
+[ow.search()](#owsearch)
+
+## ow.write()
+Writes a byte. If `power` is 1 then the wire is held high at the end for parasitically powered devices. You are responsible for eventually depowering it by calling `ow.depower()` or doing another read or write.
+
+#### Syntax
+`ow.write(pin, v, power)`
+
+#### Parameters
+- `pin` 1~12, I/O index
+- `v` byte to be written to salve device 
+- `power` 1 for wire being held high for parasitically powered devices
+
+#### Returns
+`nil`
+
+####See also
+[ow.depower()](#owdepower)
+
+## ow.write_bytes()
+Writes multi bytes. If `power` is 1 then the wire is held high at the end for parasitically powered devices. You are responsible for eventually depowering it by calling `ow.depower()` or doing another read or write.
+
+#### Syntax
+`ow.write_bytes(pin, buf, power)`
+
+#### Parameters
+- `pin` 1~12, IO index
+- `buf` string to be written to slave device
+- `power` 1 for wire being held high for parasitically powered devices
+
+#### Returns
+`nil`
+
+####See also
+[ow.depower()](#owdepower)

+ 152 - 0
docs/en/modules/pwm.md

@@ -0,0 +1,152 @@
+# pwm Module
+
+## pwm.close()
+Quit PWM mode for the specified GPIO pin.
+
+#### Syntax
+`pwm.close(pin)`
+
+#### Parameters
+`pin` 1~12, IO index
+
+#### Returns
+`nil`
+
+#### See also
+[pwm.start()](#pwmstart)
+
+## pwm.getclock()
+Get selected PWM frequency of pin.
+
+#### Syntax
+`pwm.getclock(pin)`
+
+#### Parameters
+`pin` 1~12, IO index
+
+#### Returns
+`number` PWM frequency of pin
+
+#### See also
+[pwm.setclock()](#pwmsetclock)
+
+#### See also
+[pwm.getduty()](#pwmgetduty)
+
+## pwm.getduty()
+Get selected duty cycle of pin.
+
+#### Syntax
+`pwm.getduty(pin)`
+
+#### Parameters
+`pin` 1~12, IO index
+
+#### Returns
+`number` duty cycle, max 1023
+
+#### See also
+[pwm.setduty()](#pwmsetduty)
+
+## pwm.setclock()
+Set PWM frequency.
+**Note:** Setup of the PWM frequency will synchronously change other setups as well if there are any. Only one PWM frequency can be allowed for the system.
+
+#### Syntax
+`pwm.setclock(pin, clock)`
+
+#### Parameters
+- `pin` 1~12, IO index
+- `clock` 1~1000, PWM frequency
+
+#### Returns
+`nil`
+
+#### See also
+[pwm.getclock()](#pwmgetclock)
+
+## pwm.setduty()
+Set duty cycle for a pin.
+
+#### Syntax
+`pwm.setduty(pin, duty)`
+
+#### Parameters
+- `pin` 1~12, IO index
+- `duty` 0~1023, pwm duty cycle, max 1023 (10bit)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- D1 is connected to green led
+-- D2 is connected to blue led
+-- D3 is connected to red led
+pwm.setup(1, 500, 512)
+pwm.setup(2, 500, 512)
+pwm.setup(3, 500, 512)
+pwm.start(1)
+pwm.start(2)
+pwm.start(3)
+function led(r, g, b)
+    pwm.setduty(1, g)
+    pwm.setduty(2, b)
+    pwm.setduty(3, r)
+end
+led(512, 0, 0) --  set led to red
+led(0, 0, 512) -- set led to blue.
+```
+
+## pwm.setup()
+Set pin to PWM mode. Only 6 pins can be set to PWM mode at the most.
+
+#### Syntax
+`pwm.setup(pin, clock, duty)`
+
+#### Parameters
+- `pin` 1~12, IO index
+- `clock` 1~1000, pwm frequency
+- `duty` 0~1023, pwm duty cycle, max 1023 (10bit)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- set pin index 1 as pwm output, frequency is 100Hz, duty cycle is half.
+pwm.setup(1, 100, 512)
+```
+
+#### See also
+[pwm.start()](#pwmstart)
+
+## pwm.start()
+PWM starts, the waveform is applied to the GPIO pin.
+
+#### Syntax
+`pwm.start(pin)`
+
+####Parameters
+`pin` 1~12, IO index
+
+#### Returns
+`nil`
+
+#### See also
+[pwm.stop()](#pwmstop)
+
+## pwm.stop()
+Pause the output of the PWM waveform.
+
+#### Syntax
+`pwm.stop(pin)`
+
+#### Parameters
+`pin` 1~12, IO index
+
+#### Returns
+`nil`
+
+#### See also
+[pwm.start()](#pwmstart)

Різницю між файлами не показано, бо вона завелика
+ 2 - 0
docs/en/modules/rtcfifo.md


+ 59 - 0
docs/en/modules/rtcmem.md

@@ -0,0 +1,59 @@
+# rtcmem Module
+The rtcmem module provides basic access to the [RTC](https://en.wikipedia.org/wiki/Real-time_clock) (Real Time Clock) memory.
+
+The RTC in the ESP8266 contains memory registers which survive a deep sleep, making them highly useful for keeping state across sleep cycles. Some of this memory is reserved for system use, but 128 slots (each 32bit wide) are available for application use. This module provides read and write access to these.
+
+Due to the very limited amount of memory available, there is no mechanism for arbitrating use of particular slots. It is up to the end user to be aware of which memory is used for what, and avoid conflicts. Note that some Lua modules lay claim to certain slots.
+
+This is a companion module to the [rtctime](rtctime.md) and [rtcfifo](rtcfifo.md) modules.
+
+## rtcmem.read32()
+
+Reads one or more 32bit values from RTC user memory.
+
+#### Syntax
+`rtcmem.read32(idx [, num])`
+
+#### Parameters
+  - `idx` zero-based index to start reading from
+  - `num` number of slots to read (default 1)
+
+#### Returns
+The value(s) read from RTC user memory.
+
+If `idx` is outside the valid range [0,127] this function returns nothing.
+
+If `num` results in overstepping the end of available memory, the function only returns the data from the valid slots.
+
+#### Example
+```lua
+val = rtcmem.read32(0) -- Read the value in slot 0
+val1, val2 = rtcmem.read32(42, 2) -- Read the values in slots 42 and 43
+```
+#### See also
+[`rtcmem.write32()`](#rtcmemwrite32)
+
+## rtcmem.write32()
+
+Writes one or more values to RTC user memory, starting at index `idx`.
+
+Writing to indices outside the valid range [0,127] has no effect.
+
+#### Syntax
+`rtcmem.write32(idx, val [, val2, ...])`
+
+#### Parameters
+  - `idx` zero-based index to start writing to. Auto-increments if multiple values are given.
+  - `val` value to store (32bit)
+  - `val2...` additional values to store (optional)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+rtcmem.write32(0, 53) -- Store the value 53 in slot 0
+rtcmem.write32(42, 2, 5, 7) -- Store the values 2, 5 and 7 into slots 42, 43 and 44, respectively.
+```
+#### See also
+[`rtcmem.read32()`](#rtcmemread32)

Різницю між файлами не показано, бо вона завелика
+ 6 - 0
docs/en/modules/rtctime.md


+ 40 - 0
docs/en/modules/sntp.md

@@ -0,0 +1,40 @@
+# SNTP Module
+
+The SNTP module implements a [Simple Network Time Procotol](https://en.wikipedia.org/wiki/Network_Time_Protocol#SNTP) client. This includes support for the "anycast" [NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol) mode where, if supported by the NTP server(s) in your network, it is not necessary to even know the IP address of the NTP server.
+
+When compiled together with the [rtctime](rtctime.md) module it also offers seamless integration with it, potentially reducing the process of obtaining NTP synchronization to a simple `sntp.sync()` call without any arguments.
+
+
+## sntp.sync()
+
+Attempts to obtain time synchronization.
+
+#### Syntax
+`sntp.sync([server_ip], [callback], [errcallback])`
+
+#### Parameters
+- `server_ip` if non-`nil`, that server is used. If `nil`, then the last contacted server is used. This ties in with the NTP anycast mode, where the first responding server is remembered for future synchronization requests. The easiest way to use anycast is to always pass nil for the server argument.
+- `callback` Iif provided it will be invoked on a successful synchronization, with three parameters: seconds, microseconds, and server. Note that when the [rtctime](rtctime.md) module is available, there is no need to explicitly call [`rtctime.set()`](rtctime.md#rtctimeset) - this module takes care of doing so internally automatically, for best accuracy.
+- `errcallback` failure callback with no parameters. The module automatically performs a number of retries before giving up and reporting the error.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- Best effort, use the last known NTP server (or the NTP "anycast" address 224.0.1.1 initially)
+sntp.sync()
+```
+```lua
+-- Sync time with 192.168.0.1 and print the result, or that it failed
+sntp.sync('192.168.0.1',
+  function(sec,usec,server)
+    print('sync', sec, usec, server)
+  end,
+  function()
+   print('failed!')
+  end
+)
+```
+#### See also
+[`rtctime.set()`](rtctime.md#rtctimeset)

+ 173 - 0
docs/en/modules/spi.md

@@ -0,0 +1,173 @@
+#spi module
+All transactions for sending and receiving are most-significant-bit first and least-significant last.
+For technical details of the underlying hardware refer to [metalphreak's ESP8266 HSPI articles](http://d.av.id.au/blog/tag/hspi/).
+
+## High Level Functions
+The high level functions provide a send & receive API for half- and
+full-duplex mode. Sent and received data items are restricted to 1 - 32 bit
+length and each data item is surrounded by (H)SPI CS inactive.
+
+## spi.recv()
+Receive data from SPI.
+
+#### Syntax
+`spi.recv(id, size[, default_data])`
+
+#### Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `size` number of data items to be read
+- `default_data` default data being sent on MOSI (all-1 if omitted)
+
+#### Returns
+String containing the bytes read from SPI.
+
+####See also
+[spi.send()](#spisend)
+
+## spi.send()
+Send data via SPI in half-duplex mode. Send & receive data in full-duplex mode.
+
+#### Syntax
+HALFDUPLEX:<br />
+`wrote = spi.send(id, data1[, data2[, ..., datan]])`
+
+FULLDUPLEX:<br />
+`wrote[, rdata1[, ..., rdatan]] = spi.send(id, data1[, data2[, ..., datan]])`
+
+#### Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `data` data can be either a string, a table or an integer number.<br/>Each data item is considered with `databits` number of bits.
+
+#### Returns
+- `wrote` number of written bytes
+- `rdata` received data when configured with `spi.FULLDUPLEX`<br />Same data type as corresponding data parameter.
+
+#### Example
+```lua
+=spi.send(1, 0, 255, 255, 255)
+4       255     192     32      0
+x = {spi.send(1, 0, 255, 255, 255)}
+=x[1]
+4
+=x[2]
+255
+=x[3]
+192
+=x[4]
+32
+=x[5]
+0
+=x[6]
+nil
+=#x
+5
+
+_, _, x = spi.send(1, 0, {255, 255, 255})
+=x[1]
+192
+=x[2]
+32
+=x[3]
+0
+```
+#### See also
+- [spi.setup()](#spisetup)
+- [spi.recv()](#spirecv)
+
+## spi.setup()
+Set up the SPI configuration.
+Refer to [Serial Peripheral Interface Bus](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Clock_polarity_and_phase) for details regarding the clock polarity and phase definition.
+
+#### Syntax
+`spi.setup(id, mode, cpol, cpha, databits, clock_div[, duplex_mode])`
+
+#### Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `mode` select master or slave mode
+	- `spi.MASTER`
+	- `spi.SLAVE` - **not supported currently**
+- `cpol` clock polarity selection
+	- `spi.CPOL_LOW` 
+	- `spi.CPOL_HIGH` - **not supported currently**
+- `cpha` clock phase selection
+	- `spi.CPHA_LOW`
+	- `spi.CPHA_HIGH`
+- `databits` number of bits per data item 1 - 32
+- `clock_div` SPI clock divider, f(SPI) = f(CPU) / `clock_div`
+- `duplex_mode` duplex mode
+	-  `spi.HALFDUPLEX` (default when omitted)
+	- `spi.FULLDUPLEX`
+
+#### Returns
+Number: 1
+
+## Low Level Hardware Functions
+The low level functions provide a hardware-centric API for application
+scenarios that need to excercise more complex SPI transactions. The
+programming model is built up around the HW send and receive buffers and SPI
+transactions are initiated with full control over the hardware features.
+
+## spi.get_miso()
+Extract data items from MISO buffer after `spi.transaction()`.
+
+#### Syntax
+`data1[, data2[, ..., datan]] = spi.get_miso(id, offset, bitlen, num)`
+
+#### Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `offset` bit offset into MISO buffer for first data item
+- `bitlen` bit length of a single data item
+- `num` number of data items to retrieve
+
+####Returns
+`num` data items
+
+#### See also
+[spi.transaction()](#spitransaction)
+
+## spi.set_mosi()
+Insert data items into MOSI buffer for `spi.transaction()`.
+
+#### Syntax
+`spi.set_mosi(id, offset, bitlen, data1[, data2[, ..., datan]])`
+
+####Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `offset` bit offset into MOSI buffer for inserting data1 and subsequent items
+- `bitlen` bit length of data1, data2, ...
+- `data` data items where `bitlen` number of bits are considered for the transaction.
+
+#### Returns
+`nil`
+
+#### See also
+[spi.transaction()](#spitransaction)
+
+## spi.transaction()
+Start an SPI transaction, consisting of up to 5 phases:
+
+1. Command
+2. Address
+3. MOSI
+4. Dummy
+5. MISO
+
+#### Syntax
+`spi.transaction(id, cmd_bitlen, cmd_data, addr_bitlen, addr_data, mosi_bitlen, dummy_bitlen, miso_bitlen)`
+
+#### Parameters
+- `id` SPI ID number: 0 for SPI, 1 for HSPI
+- `cmd_bitlen` bit length of the command phase (0 - 16)
+- `cmd_data` data for command phase
+- `addr_bitlen` bit length for address phase (0 - 32)
+- `addr_data` data for command phase
+- `mosi_bitlen` bit length of the MOSI phase (0 - 512)
+- `dummy_bitlen` bit length of the dummy phase (0 - 256)
+- `miso_bitlen` bit length of the MISO phase (0 - 512) for half-duplex.<br />Full-duplex mode is activated with a negative value.
+
+####Returns
+`nil`
+
+####See also
+- [spi.set_mosi()](#spisetmosi)
+- [spi.get_miso()](#spigetmiso)

+ 273 - 0
docs/en/modules/tmr.md

@@ -0,0 +1,273 @@
+# tmr Module
+
+The tmr module allows access to simple timers, the system counter and uptime.
+
+It is aimed at setting up regularly occurring tasks, timing out operations, and provide low-resolution deltas.
+
+What the tmr module is *not* however, is a time keeping module. While most timeouts are expressed in milliseconds or even microseconds, the accuracy is limited and compounding errors would lead to rather inaccurate time keeping. Consider using the [rtctime](rtctime.md) module for "wall clock" time.
+
+NodeMCU provides 7 timers, numbered 0-6. It is currently up to the user to keep track of which timers are used for what.
+
+## tmr.alarm()
+
+This is a convenience function combining [`tmr.register()`](#tmrregister) and [`tmr.start()`](#tmrstart) into a single call.
+
+To free up the resources with this timer when done using it, call [`tmr.unregister()`](#tmrunregister) on it. For one-shot timers this is not necessary, unless they were stopped before they expired.
+
+#### Parameters
+- `id` timer id (0-6)
+- `interval_ms` timer interval in milliseconds. Maximum value is 12884901. In SDKs <= 1.5.0 values >6871948 result in incorrect behaviour.
+- `mode` timer mode:
+	- `tmr.ALARM_SINGLE` a one-shot alarm (and no need to call [`tmr.unregister()`](#tmrunregister))
+	- `tmr.ALARM_SEMI` manually repeating alarm (call [`tmr.start()`](#tmrstart) to restart)
+	- `tmr.ALARM_AUTO` automatically repeating alarm
+
+#### Returns
+`true` if the timer was started, `false` on error
+
+#### Example
+```lua
+if not tmr.alarm(0, 5000, tmr.ALARM_SINGLE, function() print("hey there") end) then print("whoopsie") end
+```
+#### See also
+- [`tmr.register()`](#tmrregister)
+- [`tmr.start()`](#tmrstart)
+- [`tmr.unregister()`](#tmrunregister)
+
+## tmr.delay()
+
+Busyloops the processor for a specified number of microseconds.
+
+This is in general a **bad** idea, because nothing else gets to run, and the networking stack (and other things) can fall over as a result. The only time `tmr.delay()` may be appropriate to use is if dealing with a peripheral device which needs a (very) brief delay between commands, or similar. *Use with caution!*
+
+Also note that the actual amount of time delayed for may be noticeably greater, both as a result of timing inaccuracies as well as interrupts which may run during this time.
+
+#### Syntax
+`tmr.delay(us)`
+
+#### Parameters
+`us` microseconds to busyloop for
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+tmr.delay(100)
+```
+
+## tmr.interval()
+
+Changes a registered timer's expiry interval.
+
+#### Syntax
+`tmr.interval(id, interval_ms)`
+
+#### Parameters
+- `id` timer id (0-6)
+- `interval_ms` new timer interval in milliseconds. Maximum value is 12884901. In SDKs <= 1.5.0 values >6871948 result in incorrect behaviour.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+tmr.register(0, 5000, tmr.ALARM_SINGLE, function() print("hey there") end)
+tmr.interval(0, 3000) -- actually, 3 seconds is better!
+```
+
+## tmr.now()
+
+Returns the system counter, which counts in microseconds. Limited to 31 bits, after that it wraps around back to zero. That is essential if you use this function to [debounce or throttle GPIO input](https://github.com/hackhitchin/esp8266-co-uk/issues/2).
+
+#### Syntax
+`tmr.now()`
+
+#### Parameters
+none
+
+#### Returns
+the current value of the system counter
+
+#### Example
+```lua
+print(tmr.now())
+print(tmr.now())
+```
+
+## tmr.register()
+
+Configures a timer and registers the callback function to call on expiry.
+
+To free up the resources with this timer when done using it, call [`tmr.unregister()`](#tmrunregister) on it. For one-shot timers this is not necessary, unless they were stopped before they expired.
+
+#### Syntax
+`tmr.register(id, interval_ms, mode, func)`
+
+#### Parameters
+- `id` timer id (0-6)
+- `interval_ms` timer interval in milliseconds. Maximum value is 12884901. In SDKs <= 1.5.0 values >6871948 result in incorrect behaviour.
+- `mode` timer mode:
+	- `tmr.ALARM_SINGLE` a one-shot alarm (and no need to call [`tmr.unregister()`](#tmrunregister))
+	- `tmr.ALARM_SEMI` manually repeating alarm (call [`tmr.start()`](#tmrunregister) to restart)
+	- `tmr.ALARM_AUTO` automatically repeating alarm
+
+Note that registering does *not* start the alarm.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+tmr.register(0, 5000, tmr.ALARM_SINGLE, function() print("hey there") end)
+tmr.start(0)
+```
+#### See also
+[`tmr.alarm()`](#tmralarm)
+
+## tmr.softwd()
+
+Provides a simple software watchdog, which needs to be re-armed or disabled before it expires, or the system will be restarted.
+
+#### Syntax
+`tmr.softwd(timeout_s)`
+
+#### Parameters
+`timeout_s` watchdog timeout, in seconds. To disable the watchdog, use -1 (or any other negative value).
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+function on_success_callback()
+  tmr.softwd(-1)
+  print("Complex task done, soft watchdog disabled!")
+end
+
+tmr.softwd(5)
+-- go off and attempt to do whatever might need a restart to recover from
+complex_stuff_which_might_never_call_the_callback(on_success_callback)
+```
+
+## tmr.start()
+
+Starts or restarts a previously configured timer.
+
+#### Syntax
+`tmr.start(id)`
+
+#### Parameters
+`id` timer id (0-6)
+
+#### Returns
+`true` if the timer was started, `false` on error
+
+#### Example
+```lua
+tmr.register(0, 5000, tmr.ALARM_SINGLE, function() print("hey there") end)
+if not tmr.start(0) then print("uh oh") end
+```
+#### See also
+- [`tmr.register()`](#tmrregister)
+- [`tmr.stop()`](#tmrstop)
+- [`tmr.unregister()`](#tmrunregister)
+
+## tmr.state()
+
+Checks the state of a timer.
+
+#### Syntax
+`tmr.state(id)`
+
+#### Parameters
+`id` timer id (0-6)
+
+#### Returns
+(bool, int) or `nil`
+
+If the specified timer is registered, returns whether it is currently started and its mode. If the timer is not registered, `nil` is returned.
+
+#### Example
+```lua
+running, mode = tmr.state(0)
+```
+
+## tmr.stop()
+
+Stops a running timer, but does *not* unregister it. A stopped timer can be restarted with [`tmr.start()`](#tmrstart).
+
+#### Syntax
+`tmr.stop(id)`
+
+#### Parameters
+`id` timer id (0-6)
+
+#### Returns
+`true` if the timer was stopped, `false` on error
+
+#### Example
+```lua
+if not tmr.stop(2) then print("timer 2 not stopped, not registered?") end
+```
+#### See also
+- [`tmr.register()`](#tmrregister)
+- [`tmr.stop()`](#tmrstop)
+- [`tmr.unregister()`](#tmrunregister)
+
+## tmr.time()
+
+Returns the system uptime, in seconds. Limited to 31 bits, after that it wraps around back to zero.
+
+#### Syntax
+`tmr.time()`
+
+#### Parameters
+none
+
+#### Returns
+the system uptime, in seconds, possibly wrapped around
+
+#### Example
+```lua
+print("Uptime (probably):", tmr.time())
+```
+
+## tmr.unregister()
+
+Stops the timer (if running) and unregisters the associated callback.
+
+This isn't necessary for one-shot timers (`tmr.ALARM_SINGLE`), as those automatically unregister themselves when fired.
+
+#### Syntax
+`tmr.unregister(id)`
+
+#### Parameters
+`id` timer id (0-6)
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+tmr.unregister(0)
+```
+#### See also
+[`tmr.register()`](#tmrregister)
+
+## tmr.wdclr()
+
+Feed the system watchdog.
+
+*In general, if you ever need to use this function, you are doing it wrong.*
+
+The event-driven model of NodeMCU means that there is no need to be sitting in hard loops waiting for things to occur. Rather, simply use the callbacks to get notified when somethings happens. With this approach, there should never be a need to manually feed the system watchdog.
+
+#### Syntax
+`tmr.wdclr()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`

+ 131 - 0
docs/en/modules/tsl2561.md

@@ -0,0 +1,131 @@
+# TSL2561 Module
+
+## tsl2561.getlux()
+Reads sensor values from the device and returns calculated lux value.
+
+#### Syntax
+`tsl2561.getlux()`
+
+#### Parameters
+none
+
+#### Returns
+- `lux` the calculated illuminance in lux (lx)
+- `status` value indicating success or failure as explained below:
+    * `tsl2561.TSL2561_OK`
+    * `tsl2561.TSL2561_ERROR_I2CINIT` can't initialize I²C bus
+    * `tsl2561.TSL2561_ERROR_I2CBUSY` I²C bus busy
+    * `tsl2561.TSL2561_ERROR_NOINIT` initialize I²C bus before calling function
+    * `tsl2561.TSL2561_ERROR_LAST`
+
+#### Example
+``` lua
+status = tsl2561.init(5, 6, tsl2561.ADDRESS_FLOAT, tsl2561.PACKAGE_T_FN_CL)
+
+if status == tsl2561.TSL2561_OK then
+    lux = tsl2561.getlux()
+    print("Illuminance: "..lux.." lx") 
+end
+```
+
+## tsl2561.getrawchannels()
+Reads the device's 2 sensors and returns their values.
+
+#### Syntax
+`tsl2561.getrawchannels()`
+
+#### Parameters
+none
+
+#### Returns
+- `ch0` value of the broad spectrum sensor
+- `ch1` value of the IR sensor
+- `status` value indicating success or failure as explained below:
+    * `tsl2561.TSL2561_OK`
+    * `tsl2561.TSL2561_ERROR_I2CINIT` can't initialize I²C bus
+    * `tsl2561.TSL2561_ERROR_I2CBUSY` I²C bus busy
+    * `tsl2561.TSL2561_ERROR_NOINIT` initialize I²C bus before calling function
+    * `tsl2561.TSL2561_ERROR_LAST`
+
+#### Example
+``` lua
+status = tsl2561.init(5, 6, tsl2561.ADDRESS_FLOAT, tsl2561.PACKAGE_T_FN_CL)
+
+if status == tsl2561.TSL2561_OK then
+    ch0, ch1 = tsl2561.getrawchannels()
+    print("Raw values: "..ch0, ch1)
+    lux = tsl2561.getlux()
+    print("Illuminance: "..lux.." lx") 
+end
+```
+
+## tsl2561.init()
+Initializes the device on pins sdapin & sclpin. Optionally also configures the devices address and package. Default: address pin floating (0x39) and FN package.
+
+#### Syntax
+` tsl2561.init(sdapin, sclpin[, address[, package]])`
+
+#### Parameters
+- `sdapin` pin number of the device's I²C sda connection
+- `sclpin` pin number of the device's I²C scl connection
+- `address` optional address of the device on the I²C bus
+    * `tsl2561.ADDRESS_GND`
+    * `tsl2561.ADDRESS_FLOAT` (default when omitted)
+    * `tsl2561.ADDRESS_VDD`
+- `package` optional device's package type (slight difference in lux calculation)
+    * `tsl2561.PACKAGE_CS`
+    * `tsl2561.PACKAGE_T_FN_CL` (default when omitted)
+
+#### Returns
+`status` value indicating success or failure as explained below:
+
+- `tsl2561.TSL2561_OK`
+- `tsl2561.TSL2561_ERROR_I2CINIT` can't initialize I²C bus
+- `tsl2561.TSL2561_ERROR_I2CBUSY` I²C bus busy
+- `tsl2561.TSL2561_ERROR_NOINIT` Initialize I²C bus before calling function
+- `tsl2561.TSL2561_ERROR_LAST`
+
+#### Example
+``` lua
+status = tsl2561.init(5, 6, tsl2561.ADDRESS_FLOAT, tsl2561.PACKAGE_T_FN_CL)
+if status == tsl2561.TSL2561_OK then
+    lux = tsl2561.getlux()
+    print("Illuminance: "..lux.." lx") 
+end
+```
+
+## tsl2561.settiming()
+Sets the integration time and gain settings of the device. When `tls2561.init()` is called, these values default to 402 ms and no gain.
+
+#### Syntax
+`tsl2561.settiming(integration, gain)`
+
+#### Parameters
+- `integration` sets the device's integration period. Valid options are:
+    * `tsl2561.INTEGRATIONTIME_13MS`
+    * `tsl2561.INTEGRATIONTIME_101MS`
+    * `tsl2561.INTEGRATIONTIME_402MS` (default when omitted)
+- `gain` sets the device's gain. Valid options are:
+    * `tsl2561.GAIN_1X` (default when omitted)
+    * `tsl2561.GAIN_16X`
+
+#### Returns
+`status` value indicating success or failure as explained below:
+
+- `tsl2561.TSL2561_OK`
+- `tsl2561.TSL2561_ERROR_I2CINIT` can't initialize I²C bus
+- `tsl2561.TSL2561_ERROR_I2CBUSY` I²C bus busy
+- `tsl2561.TSL2561_ERROR_NOINIT` initialize I²C bus before calling function
+- `tsl2561.TSL2561_ERROR_LAST`
+
+#### Example
+``` lua
+status = tsl2561.init(5, 6, tsl2561.ADDRESS_FLOAT, tsl2561.PACKAGE_T_FN_CL)
+if status == tsl2561.TSL2561_OK then
+    status = tsl2561.settiming(tsl2561.INTEGRATIONTIME_101MS, tsl2561.GAIN_16X)
+end
+if status == tsl2561.TSL2561_OK then
+    lux = tsl2561.getlux()
+    print("Illuminance: "..lux.." lx") 
+end
+```

Різницю між файлами не показано, бо вона завелика
+ 286 - 0
docs/en/modules/u8g.md


+ 103 - 0
docs/en/modules/uart.md

@@ -0,0 +1,103 @@
+# UART Module
+The [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter) (Universal asynchronous receiver/transmitter) module allows configuration of and communication over the UART serial port.
+
+## uart.alt()
+Change UART pin assignment.
+
+#### Syntax
+`uart.alt(on)`
+
+#### Parameters
+`on`:
+- `0` use standard pins
+- `1` use alternate pins GPIO13 and GPIO15
+
+#### Returns
+`nil`
+
+## uart.on()
+
+Sets the callback function to handle UART events.
+
+Currently only the "data" event is supported.
+
+#### Syntax
+`uart.on(method, [number/end_char], [function], [run_input])`
+
+#### Parameters
+- `method` "data", data has been received on the UART
+- `number/end_char`
+	- if pass in a number n<255, the callback will called when n chars are received.
+	- if n=0, will receive every char in buffer.
+	- if pass in a one char string "c", the callback will called when "c" is encounterd, or max n=255 received.
+- `function` callback function, event "data" has a callback like this: `function(data) end`
+- `run_input` 0 or 1. If 0, input from UART will not go into Lua interpreter, can accept binary data. If 1, input from UART will go into Lua interpreter, and run.
+
+To unregister the callback, provide only the "data" parameter.
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+-- when 4 chars is received.
+uart.on("data", 4,
+  function(data)
+	print("receive from uart:", data)
+	if data=="quit" then
+	  uart.on("data") -- unregister callback function
+	end
+end, 0)
+-- when '\r' is received.
+uart.on("data", "\r",
+  function(data)
+	print("receive from uart:", data)
+	if data=="quit\r" then
+	  uart.on("data") -- unregister callback function
+	end
+end, 0)
+```
+
+## uart.setup()
+
+(Re-)configures the communication parameters of the UART.
+
+#### Syntax
+`uart.setup(id, baud, databits, parity, stopbits, echo)`
+
+#### Parameters
+- `id` always zero, only one uart supported
+- `baud` one of 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 460800, 921600, 1843200, 2686400
+- `databits` one of 5, 6, 7, 8
+- `parity` `uart.PARITY_NONE`, `uart.PARITY_ODD`, or `uart.PARITY_EVEN`
+- `stopbits` `uart.STOPBITS_1`, `uart.STOPBITS_1_5`, or `uart.STOPBITS_2`
+- `echo` if 0, disable echo, otherwise enable echo
+
+#### Returns
+configured baud rate (number)
+
+#### Example
+```lua
+-- configure for 9600, 8N1, with echo
+uart.setup(0, 9600, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
+```
+
+## uart.write()
+
+Write string or byte to the UART.
+
+#### Syntax
+`uart.write(id, data1 [, data2, ...])`
+
+#### Parameters
+- `id` always 0, only one UART supported
+- `data1`... string or byte to send via UART
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+uart.write(0, "Hello, world\n")
+```
+

+ 266 - 0
docs/en/modules/ucg.md

@@ -0,0 +1,266 @@
+# ucg Module
+Ucglib is a graphics library developed at [olikraus/ucglib](https://github.com/olikraus/ucglib) with support for color TFT displays. The NodeMCU firmware supports a subset of these:
+
+- ILI9163
+- ILI9341
+- PCF8833
+- SEPS225
+- SSD1331
+- SSD1351
+- ST7735
+
+This integration is based on [v1.3.3](https://github.com/olikraus/Ucglib_Arduino/releases/tag/v1.3.3).
+
+## Overview
+
+### SPI Connection
+
+The HSPI module is used ([more information](http://d.av.id.au/blog/esp8266-hardware-spi-hspi-general-info-and-pinout/)), so certain pins are fixed:
+
+* HSPI CLK  = GPIO14
+* HSPI MOSI = GPIO13
+* HSPI MISO = GPIO12 (not used)
+
+All other pins can be assigned to any available GPIO:
+
+* CS
+* D/C
+* RES (optional for some displays)
+
+Also refer to the initialization sequence eg in [GraphicsTest.lua](https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/ucglib/GraphicsRest.lua):
+```lua
+spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 8)
+```
+
+### Library Usage
+The Lua bindings for this library closely follow ucglib's object oriented C++ API. Based on the ucg class, you create an object for your display type.
+
+ILI9341 via SPI:
+```lua
+cs  = 8 -- GPIO15, pull-down 10k to GND
+dc  = 4 -- GPIO2
+res = 0 -- GPIO16, RES is optional YMMV
+disp = ucg.ili9341_18x240x320_hw_spi(cs, dc, res)
+```
+
+This object provides all of ucglib's methods to control the display.
+Again, refer to [GraphicsTest.lua](https://github.com/nodemcu/nodemcu-firmware/blob/master/lua_examples/ucglib/GraphicsTest.lua) to get an impression how this is achieved with Lua code. Visit the [ucglib homepage](https://github.com/olikraus/ucglib) for technical details.
+
+### Displays
+To get access to the display constructors, add the desired entries to the display table in [app/include/ucg_config.h](https://github.com/nodemcu/nodemcu-firmware/blob/master/app/include/ucg_config.h):
+```c
+#define UCG_DISPLAY_TABLE                          \
+    UCG_DISPLAY_TABLE_ENTRY(ili9341_18x240x320_hw_spi, ucg_dev_ili9341_18x240x320, ucg_ext_ili9341_18) \
+    UCG_DISPLAY_TABLE_ENTRY(st7735_18x128x160_hw_spi, ucg_dev_st7735_18x128x160, ucg_ext_st7735_18) \
+```
+
+### Fonts
+ucglib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in [app/include/ucg_config.h](https://github.com/nodemcu/nodemcu-firmware/blob/master/app/include/ucg_config.h) and recompile. Simply add the desired fonts to the font table:
+```c
+#define UCG_FONT_TABLE                              \
+    UCG_FONT_TABLE_ENTRY(font_7x13B_tr)             \
+    UCG_FONT_TABLE_ENTRY(font_helvB12_hr)           \
+    UCG_FONT_TABLE_ENTRY(font_helvB18_hr)           \
+    UCG_FONT_TABLE_ENTRY(font_ncenR12_tr)           \
+    UCG_FONT_TABLE_ENTRY(font_ncenR14_hr)
+```
+They'll be available as `ucg.<font_name>` in Lua.
+
+## Display Drivers
+
+Initialize a display via Hardware SPI.
+
+- `ili9163_18x128x128_hw_spi()`
+- `ili9341_18x240x320_hw_spi()`
+- `pcf8833_16x132x132_hw_spi()`
+- `seps225_16x128x128_univision_hw_spi()`
+- `ssd1351_18x128x128_hw_spi()`
+- `ssd1351_18x128x128_ft_hw_spi()`
+- `ssd1331_18x96x64_univision_hw_spi()`
+- `st7735_18x128x160_hw_spi()`
+
+#### Syntax
+`ucg.st7735_18x128x160_hw_spi(cs, dc[, res])`
+
+#### Parameters
+- `cs` GPIO pin for /CS
+- `dc` GPIO pin for DC
+- `res` GPIO pin for /RES (optional)
+
+#### Returns
+ucg display object
+
+#### Example
+```lua
+spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
+
+cs  = 8 -- GPIO15, pull-down 10k to GND
+dc  = 4 -- GPIO2
+res = 0 -- GPIO16, RES is optional YMMV
+disp = ucg.st7735_18x128x160_hw_spi(cs, dc, res)
+```
+
+## Constants
+Constants for various functions.
+
+`ucg.FONT_MODE_TRANSPARENT`, `ucg.FONT_MODE_SOLID`, `ucg.DRAW_UPPER_RIGHT`,
+`ucg.DRAW_UPPER_LEFT`, `ucg.DRAW_LOWER_RIGHT`, `ucg.DRAW_LOWER_LEFT`, `ucg.DRAW_ALL`
+
+`ucg.font_7x13B_tr`, ...
+
+# ucg.disp Sub-Module
+
+## ucg.disp:begin()
+See [ucglib begin()](https://github.com/olikraus/ucglib/wiki/reference#begin).
+
+## ucg.disp:clearScreen()
+See [ucglib clearScreen()](https://github.com/olikraus/ucglib/wiki/reference#clearscreen).
+
+## ucg.disp:draw90Line()
+See [ucglib draw90Line()](https://github.com/olikraus/ucglib/wiki/reference#draw90line).
+
+## ucg.disp:drawBox()
+See [ucglib drawBox()](https://github.com/olikraus/ucglib/wiki/reference#drawbox).
+
+## ucg.disp:drawCircle()
+See [ucglib drawCircle()](https://github.com/olikraus/ucglib/wiki/reference#drawcircle).
+
+## ucg.disp:drawDisc()
+See [ucglib drawDisc()](https://github.com/olikraus/ucglib/wiki/reference#drawdisc).
+
+## ucg.disp:drawFrame()
+See [ucglib drawFrame()](https://github.com/olikraus/ucglib/wiki/reference#drawframe).
+
+## ucg.disp:drawGlyph()
+See [ucglib drawGlyph()](https://github.com/olikraus/ucglib/wiki/reference#drawglyph).
+
+## ucg.disp:drawGradientBox()
+See [ucglib drawGradientBox()](https://github.com/olikraus/ucglib/wiki/reference#drawgradientbox).
+
+## ucg.disp:drawGradientLine()
+See [ucglib drawGradientLine()](https://github.com/olikraus/ucglib/wiki/reference#drawgradientline).
+
+## ucg.disp:drawHLine()
+See [ucglib drawHLine()](https://github.com/olikraus/ucglib/wiki/reference#drawhline).
+
+## ucg.disp:drawLine()
+See [ucglib drawLine()](https://github.com/olikraus/ucglib/wiki/reference#drawline).
+
+## ucg.disp:drawPixel()
+See [ucglib drawPixel()](https://github.com/olikraus/ucglib/wiki/reference#drawpixel).
+
+## ucg.disp:drawRBox()
+See [ucglib drawRBox()](https://github.com/olikraus/ucglib/wiki/reference#drawrbox).
+
+## ucg.disp:drawRFrame()
+See [ucglib drawRFrame()](https://github.com/olikraus/ucglib/wiki/reference#drawrframe).
+
+## ucg.disp:drawString()
+See [ucglib drawString()](https://github.com/olikraus/ucglib/wiki/reference#drawstring).
+
+## ucg.disp:drawTetragon()
+See [ucglib drawTetragon()](https://github.com/olikraus/ucglib/wiki/reference#drawtetragon).
+
+## ucg.disp:drawTriangle()
+See [ucglib drawTriangle()](https://github.com/olikraus/ucglib/wiki/reference#drawrtiangle).
+
+## ucg.disp:drawVLine()
+See [ucglib drawVline()](https://github.com/olikraus/ucglib/wiki/reference#drawvline).
+
+## ucg.disp:getFontAscent()
+See [ucglib getFontAscent()](https://github.com/olikraus/ucglib/wiki/reference#getfontascent).
+
+## ucg.disp:getFontDescent()
+See [ucglib getFontDescent()](https://github.com/olikraus/ucglib/wiki/reference#getfontdescent).
+
+## ucg.disp:getHeight()
+See [ucglib getHeight()](https://github.com/olikraus/ucglib/wiki/reference#getheight).
+
+## ucg.disp:getStrWidth()
+See [ucglib getStrWidth()](https://github.com/olikraus/ucglib/wiki/reference#getstrwidth).
+
+## ucg.disp:getWidth()
+See [ucglib getWidth()](https://github.com/olikraus/ucglib/wiki/reference#getwidth).
+
+## ucg.disp:print()
+See [ucglib print()](https://github.com/olikraus/ucglib/wiki/reference#print).
+
+## ucg.disp:setClipRange()
+See [ucglib setClipRange()](https://github.com/olikraus/ucglib/wiki/reference#setcliprange).
+
+## ucg.disp:setColor()
+See [ucglib setColor()](https://github.com/olikraus/ucglib/wiki/reference#setcolor).
+
+## ucg.disp:setFont()
+ucglib comes with a wide range of fonts for small displays. Since they need to be compiled into the firmware image, you'd need to include them in [app/include/ucg_config.h](https://github.com/nodemcu/nodemcu-firmware/blob/master/app/include/ucg_config.h) and recompile. Simply add the desired fonts to the font table:
+```c
+#define UCG_FONT_TABLE                              \
+    UCG_FONT_TABLE_ENTRY(font_7x13B_tr)             \
+    UCG_FONT_TABLE_ENTRY(font_helvB12_hr)           \
+    UCG_FONT_TABLE_ENTRY(font_helvB18_hr)           \
+    UCG_FONT_TABLE_ENTRY(font_ncenR12_tr)           \
+    UCG_FONT_TABLE_ENTRY(font_ncenR14_hr)
+```
+They'll be available as `ucg.<font_name>` in Lua.
+
+#### Syntax
+`disp:setFont(font)`
+
+#### Parameters
+`font` constant to identify pre-compiled font
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+disp:setFont(ucg.font_7x13B_tr)
+```
+
+#### See also
+[ucglib setFont()](https://github.com/olikraus/ucglib/wiki/reference#setfont)
+
+## ucg.disp:setFontMode()
+See [ucglib setFontMode()](https://github.com/olikraus/ucglib/wiki/reference#setfontmode).
+
+## ucg.disp:setFontPosBaseline()
+See [ucglib setFontPosBaseline()](https://github.com/olikraus/ucglib/wiki/reference#setfontposbaseline).
+
+## ucg.disp:setFontPosBottom()
+See [ucglib setFontPosBottom()](https://github.com/olikraus/ucglib/wiki/reference#setfontposbottom).
+
+## ucg.disp:setFontPosCenter()
+See [ucglib setFontPosCenter()](https://github.com/olikraus/ucglib/wiki/reference#setfontposcenter).
+
+## ucg.disp:setFontPosTop()
+See [ucglib setFontPosTop()](https://github.com/olikraus/ucglib/wiki/reference#setfontpostop).
+
+## ucg.disp:setMaxClipRange()
+See [ucglib setMaxClipRange()](https://github.com/olikraus/ucglib/wiki/reference#setmaxcliprange).
+
+## ucg.disp:setPrintDir()
+See [ucglib setPrintDir()](https://github.com/olikraus/ucglib/wiki/reference#setprintdir).
+
+## ucg.disp:setPrintPos()
+See [ucglib setPrintPos()](https://github.com/olikraus/ucglib/wiki/reference#setprintpos).
+
+## ucg.disp:setRotate90()
+See [ucglib setRotate90()](https://github.com/olikraus/ucglib/wiki/reference#setrotate90).
+
+## ucg.disp:setRotate180()
+See [ucglib setRotate180()](https://github.com/olikraus/ucglib/wiki/reference#setrotate180).
+
+## ucg.disp:setRotate270()
+See [ucglib setRotate270()](https://github.com/olikraus/ucglib/wiki/reference#setrotate270).
+
+## ucg.disp:setScale2x2()
+See [ucglib setScale2x2()](https://github.com/olikraus/ucglib/wiki/reference#setscale2x2).
+
+## ucg.disp:undoClipRange()
+See [ucglib undoClipRange()](https://github.com/olikraus/ucglib/wiki/reference#undocliprange).
+
+## ucg.disp:undoRotate()
+See [ucglib undoRotate()](https://github.com/olikraus/ucglib/wiki/reference#undorotate).
+
+## ucg.disp:undoScale()
+See [ucglib undoScale()](https://github.com/olikraus/ucglib/wiki/reference#undoscale).

+ 933 - 0
docs/en/modules/wifi.md

@@ -0,0 +1,933 @@
+# WiFi Module
+The NodeMCU WiFi control is spread across several tables:
+
+- `wifi` for overall WiFi configuration
+- [`wifi.sta`](#wifista-module) for station mode functions
+- [`wifi.ap`](#wifiap-module) for wireless access point (WAP or simply AP) functions
+- [`wifi.ap.dhcp`](#wifiapdhcp-module) for DHCP server control
+
+## wifi.getchannel()
+
+Gets the current WiFi channel.
+
+#### Syntax
+`wifi.getchannel()`
+
+#### Parameters
+`nil`
+
+#### Returns
+current WiFi channel
+
+#### Example
+```lua
+print(wifi.getchannel())
+```
+
+## wifi.getmode()
+
+Gets WiFi operation mode.
+
+#### Syntax
+`wifi.getmode()`
+
+#### Parameters
+`nil`
+
+#### Returns
+The WiFi mode, as one of the `wifi.STATION`, `wifi.SOFTAP`, `wifi.STATIONAP` or `wifi.NULLMODE` constants.
+
+#### See also
+[`wifi.setmode()`](#wifisetmode)
+
+## wifi.getphymode()
+
+Gets WiFi physical mode.
+
+#### Syntax
+`wifi.getpymode()`
+
+#### Parameters
+none
+
+#### Returns
+The current physical mode as one of `wifi.PHYMODE_B`, `wifi.PHYMODE_G` or `wifi.PHYMODE_N`.
+
+#### See also
+[`wifi.setphymode()`](#wifisetphymode)
+
+## wifi.setmode()
+
+Configures the WiFi mode to use. NodeMCU can run in one of four WiFi modes:
+
+- Station mode, where the NodeMCU device joins an existing network
+- Access point (AP) mode, where it creates its own network that others can join
+- Station + AP mode, where it both creates its own network while at the same time being joined to another existing network
+- WiFi off
+
+When using the combined Station + AP mode, the same channel will be used for both networks as the radio can only listen on a single channel.
+
+#### Syntax
+`wifi.setmode(mode)`
+
+#### Parameters
+`mode` value should be one of
+
+- `wifi.STATION` for when the device is connected to a WiFi router. This is often done to give the device access to the Internet.
+- `wifi.SOFTAP` for when the device is acting *only* as an access point. This will allow you to see the device in the list of WiFi networks (unless you hide the SSID, of course). In this mode your computer can connect to the device, creating a local area network. Unless you change the value, the NodeMCU device will be given a local IP address of 192.168.4.1 and assign your computer the next available IP address, such as 192.168.4.2.
+- `wifi.STATIONAP` is the combination of `wifi.STATION` and `wifi.SOFTAP`. It allows you to create a local WiFi connection *and* connect to another WiFi router.
+- `wifi.NULLMODE` to switch off WiFi
+
+#### Returns
+current mode after setup
+
+#### Example
+```lua
+wifi.setmode(wifi.STATION)
+```
+
+#### See also
+[`wifi.getmode()`](#wifigetmode)
+
+## wifi.setphymode()
+
+Sets WiFi physical mode.
+ 
+- `wifi.PHYMODE_B`
+    802.11b, more range, low Transfer rate, more current draw
+- `wifi.PHYMODE_G`
+    802.11g, medium range, medium transfer rate, medium current draw
+- `wifi.PHYMODE_N`
+    802.11n, least range, fast transfer rate, least current draw (STATION ONLY)
+Information from the Espressif datasheet v4.3
+
+|           Parameters                        |Typical Power Usage|
+|---------------------------------------------|-------------------|
+|Tx 802.11b, CCK 11Mbps, P OUT=+17dBm         |     170 mA        |
+|Tx 802.11g, OFDM 54Mbps, P OUT =+15dBm       |     140 mA        |
+|Tx 802.11n, MCS7 65Mbps, P OUT =+13dBm       |     120 mA        |
+|Rx 802.11b, 1024 bytes packet length, -80dBm |      50 mA        |
+|Rx 802.11g, 1024 bytes packet length, -70dBm |      56 mA        |
+|Rx 802.11n, 1024 bytes packet length, -65dBm |      56 mA        |
+
+#### Syntax
+`wifi.setphymode(mode)`
+
+#### Parameters
+`mode` one of the following 
+
+- `wifi.PHYMODE_B`
+- `wifi.PHYMODE_G`
+- `wifi.PHYMODE_N`
+
+#### Returns
+physical mode after setup
+
+#### See also
+[`wifi.getphymode()`](#wifigetphymode)
+
+## wifi.sleeptype()
+
+Configures the WiFi modem sleep type.
+
+#### Syntax
+`wifi.sleeptype(type_wanted)`
+
+#### Parameters
+`type_wanted` one of the following:
+
+- `wifi.NONE_SLEEP` to keep the modem on at all times
+- `wifi.LIGHT_SLEEP` to allow the modem to power down under some circumstances
+- `wifi.MODEM_SLEEP` to power down the modem as much as possible
+
+#### Returns
+The actual sleep mode set, as one of `wifi.NONE_SLEEP`, `wifi.LIGHT_SLEEP` or `wifi.MODEM_SLEEP`.
+
+#### See also
+- [`node.dsleep()`](node.md#nodedsleep)
+- [`rtctime.dsleep()`](rtctime.md#rtctimedsleep)
+
+## wifi.startsmart()
+
+Starts to auto configuration, if success set up SSID and password automatically.
+
+Intended for use with SmartConfig apps, such as Espressif's [Android & iOS app](https://github.com/espressifapp).
+
+Only usable in `wifi.STATION` mode.
+
+#### Syntax
+`wifi.startsmart(type, callback)`
+
+#### Parameters
+- `type` 0 for ESP\_TOUCH, or 1 for AIR\_KISS.
+- `callback` a callback function of the form `function(ssid, password) end` which gets called after configuration.
+
+#### Returns
+`nil`
+
+#### Example
+
+```lua
+wifi.setmode(wifi.STATION)
+wifi.startsmart(0,
+	function(ssid, password)
+		print(string.format("Success. SSID:%s ; PASSWORD:%s", ssid, password))
+	end
+)
+```
+
+#### See also
+[`wifi.stopsmart()`](#wifistopsmart)
+
+## wifi.stopsmart()
+
+Stops the smart configuring process.
+
+#### Syntax
+`wifi.stopsmart()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### See also
+[`wifi.startsmart()`](#wifistartsmart)
+
+# wifi.sta Module
+
+## wifi.sta.autoconnect()
+
+Auto connects to AP in station mode.
+
+#### Syntax
+`wifi.sta.autoconnect(auto)`
+
+#### Parameters
+`auto` 0 to disable auto connecting, 1 to enable auto connecting
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+wifi.sta.autoconnect(1)
+```
+
+#### See also
+- [`wifi.sta.config()`](#wifistaconfig)
+- [`wifi.sta.connect()`](#wifistaconnect)
+- [`wifi.sta.disconnect()`](#wifistadisconnect)
+
+## wifi.sta.config()
+
+Sets the WiFi station configuration.
+
+#### Syntax
+`wifi.sta.config(ssid, password[, auto[, bssid]])`
+
+#### Parameters
+
+- `ssid` string which is less than 32 bytes.
+- `password` string which is 8-64 or 0 bytes. Empty string indicates an open WiFi access point.
+- `auto` value of 0 or 1 (default)
+	- 0, Disable auto connect and remain disconnected from access point
+	- 1, Enable auto connect and connect to access point
+- `bssid` string that contains the MAC address of the access point (optional)
+	- You can set BSSID if you have multiple access points with the same SSID.
+ 	- Note: if you set BSSID for a specific SSID and would like to configure station to connect to the same SSID only without the BSSID requirement, you MUST first configure to station to a different SSID first, then connect to the desired SSID
+ 	- The following formats are valid:
+		- "DE-C1-A5-51-F1-ED"
+		- "AC-1D-1C-B1-0B-22"
+		- "DE AD BE EF 7A C0"
+
+#### Returns
+`nil`
+
+#### Example
+
+```lua
+--Connect to access point automatically when in range
+wifi.sta.config("myssid", "password")
+
+--Connect to Unsecured access point automatically when in range
+wifi.sta.config("myssid", "")
+  
+--Connect to access point, User decides when to connect/disconnect to/from AP
+wifi.sta.config("myssid", "mypassword", 0)
+wifi.sta.connect()
+-- ... do some WiFi stuff
+wifi.sta.disconnect()
+   
+--Connect to specific access point automatically when in range
+wifi.sta.config("myssid", "mypassword", "12:34:56:78:90:12")
+
+--Connect to specific access point, User decides when to connect/disconnect to/from AP
+wifi.sta.config("myssid", "mypassword", 0, "12:34:56:78:90:12")
+wifi.sta.connect()
+-- ... do some WiFi stuff
+wifi.sta.disconnect()
+```
+
+#### See also
+- [`wifi.sta.connect()`](#wifistaconnect)
+- [`wifi.sta.disconnect()`](#wifistadisconnect)
+
+## wifi.sta.connect()
+
+Connects to AP in station mode.
+
+#### Syntax
+`wifi.sta.connect()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+wifi.sta.connect()
+```
+
+#### See also
+- [`wifi.sta.disconnect()`](#wifistadisconnect)
+- [`wifi.sta.config()`](#wifistaconfig)
+
+## wifi.sta.disconnect()
+
+Disconnects from AP in station mode.
+
+#### Syntax
+`wifi.sta.disconnect()`
+
+#### Parameters
+none
+
+#### Returns
+`nil`
+
+#### See also
+- [`wifi.sta.config()`](#wifistaconfig)
+- [`wifi.sta.connect()`](#wifistaconnect)
+
+## wifi.sta.eventMonReg()
+
+Registers callbacks for WiFi station status events.
+
+####  Syntax
+- `wifi.sta.eventMonReg(wifi_status, function([previous_state]))`
+- `wifi.sta.eventMonReg(wifi.status, "unreg")`
+
+####  Parameters
+- `wifi_status` WiFi status you would like to set callback for, one of: 
+    - `wifi.STA_IDLE`
+    - `wifi.STA_CONNECTING`
+    - `wifi.STA_WRONGPWD`
+    - `wifi.STA_APNOTFOUND`
+    - `wifi.STA_FAIL`
+    - `wifi.STA_GOTIP`
+- `function` function to perform when event occurs
+- `"unreg"` unregister previously registered callback
+- `previous_state` previous wifi_state(0 - 5)
+
+####  Returns
+`nil`
+
+####  Example
+```lua 
+--register callback
+wifi.sta.eventMonReg(wifi.STA_IDLE, function() print("STATION_IDLE") end)
+wifi.sta.eventMonReg(wifi.STA_CONNECTING, function() print("STATION_CONNECTING") end)
+wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() print("STATION_WRONG_PASSWORD") end)
+wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() print("STATION_NO_AP_FOUND") end)
+wifi.sta.eventMonReg(wifi.STA_FAIL, function() print("STATION_CONNECT_FAIL") end)
+wifi.sta.eventMonReg(wifi.STA_GOTIP, function() print("STATION_GOT_IP") end)
+  
+--register callback: use previous state
+wifi.sta.eventMonReg(wifi.STA_CONNECTING, function(previous_State)
+	if(previous_State==wifi.STA_GOTIP) then 
+		print("Station lost connection with access point\n\tAttempting to reconnect...")
+	else
+		print("STATION_CONNECTING")
+	end
+end)
+  
+--unregister callback
+wifi.sta.eventMonReg(wifi.STA_IDLE, "unreg")
+```
+#### See also
+- [`wifi.sta.eventMonStart()`](#wifistaeventmonstart)
+- [`wifi.sta.eventMonStop()`](#wifistaeventmonstop)
+
+## wifi.sta.eventMonStart()
+
+Starts WiFi station event monitor.
+
+####  Syntax
+`wifi.sta.eventMonStart([ms])`
+
+### Parameters
+`ms` interval between checks in milliseconds, defaults to 150ms if not provided
+
+####  Returns
+`nil`
+
+####  Example
+```lua
+--start WiFi event monitor with default interval
+wifi.sta.eventMonStart()
+
+--start WiFi event monitor with 100ms interval
+wifi.sta.eventMonStart(100)
+```
+
+#### See also
+- [`wifi.sta.eventMonReg()`](#wifistaeventmonreg)
+- [`wifi.sta.eventMonStop()`](#wifistaeventmonstop)
+- 
+## wifi.sta.eventMonStop()
+
+Stops WiFi station event monitor.
+####  Syntax
+`wifi.sta.eventMonStop(["unreg all"])`
+
+####  Parameters
+`"unreg all"` unregister all previously registered functions
+
+####  Returns
+`nil`
+
+####  Example
+```lua
+--stop WiFi event monitor
+wifi.sta.eventMonStop()
+
+--stop WiFi event monitor and unregister all callbacks
+wifi.sta.eventMonStop("unreg all")
+```
+
+#### See also
+- [`wifi.sta.eventMonReg()`](#wifistaeventmonreg)
+- [`wifi.sta.eventMonStart()`](#wifistaeventmonstart)
+
+## wifi.sta.getap()
+
+Scans AP list as a Lua table into callback function.
+
+#### Syntax
+`wifi.sta.getap([[cfg], format,] callback(table))`
+
+#### Parameters
+- `cfg` table that contains scan configuration
+	- `ssid` SSID == nil, don't filter SSID 
+	- `bssid` BSSID == nil, don't filter BSSID
+	- `channel` channel == 0, scan all channels, otherwise scan set channel (default is 0)
+	- `show_hidden` show_hidden == 1, get info for router with hidden SSID (default is 0)
+- `format` select output table format, defaults to 0
+	- 0: old format (SSID : Authmode, RSSI, BSSID, Channel), any duplicate SSIDs will be discarded
+	- 1: new format (BSSID : SSID, RSSI, auth mode, Channel)
+- `callback(table)` a callback function to receive the AP table when the scan is done. This function receives a table, the key is the BSSID, the value is other info in format: SSID, RSSID, auth mode, channel.
+
+#### Returns
+`nil`
+
+#### Example
+
+```lua
+-- print AP list in old format (format not defined)
+function listap(t)
+	for k,v in pairs(t) do
+		print(k.." : "..v)
+	end
+end
+wifi.sta.getap(listap)
+
+-- Print AP list that is easier to read
+function listap(t) -- (SSID : Authmode, RSSI, BSSID, Channel)
+	print("\n"..string.format("%32s","SSID").."\tBSSID\t\t\t\t  RSSI\t\tAUTHMODE\tCHANNEL")
+	for ssid,v in pairs(t) do
+		local authmode, rssi, bssid, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]+)")
+		print(string.format("%32s",ssid).."\t"..bssid.."\t  "..rssi.."\t\t"..authmode.."\t\t\t"..channel)
+	end
+end
+wifi.sta.getap(listap)
+	
+-- print AP list in new format
+function listap(t)
+	for k,v in pairs(t) do
+		print(k.." : "..v)
+	end
+end
+wifi.sta.getap(1, listap)
+
+-- Print AP list that is easier to read
+function listap(t) -- (SSID : Authmode, RSSI, BSSID, Channel)
+ 	print("\n\t\t\tSSID\t\t\t\t\tBSSID\t\t\t  RSSI\t\tAUTHMODE\t\tCHANNEL")
+  	for bssid,v in pairs(t) do
+   		local ssid, rssi, authmode, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]*)")
+    	print(string.format("%32.s",ssid).."\t"..bssid.."\t  "..rssi.."\t\t"..authmode.."\t\t\t"..channel)
+	end
+end
+wifi.sta.getap(1, listap)
+
+--check for specific AP
+function listap(t)
+ 	print("\n\t\t\tSSID\t\t\t\t\tBSSID\t\t\t  RSSI\t\tAUTHMODE\t\tCHANNEL")
+	for bssid,v in pairs(t) do
+		local ssid, rssi, authmode, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]*)")
+		print(string.format("%32.s",ssid).."\t"..bssid.."\t  "..rssi.."\t\t"..authmode.."\t\t\t"..channel)
+	end
+end
+scan_cfg = {}
+scan_cfg.ssid = "myssid" 
+scan_cfg.bssid = "AA:AA:AA:AA:AA:AA" 
+scan_cfg.channel = 0
+scan_cfg.show_hidden = 1
+wifi.sta.getap(scan_cfg, 1, listap)
+
+--get RSSI for currently configured AP
+function listap(t)
+	for bssid,v in pairs(t) do
+		local ssid, rssi, authmode, channel = string.match(v, "([^,]+),([^,]+),([^,]+),([^,]*)")
+		print("CURRENT RSSI IS: "..rssi)
+	end
+end
+ssid, tmp, bssid_set, bssid=wifi.sta.getconfig() 
+
+scan_cfg = {}
+scan_cfg.ssid = ssid 
+if bssid_set == 1 then scan_cfg.bssid = bssid else scan_cfg.bssid = nil end
+scan_cfg.channel = wifi.getchannel()
+scan_cfg.show_hidden = 0
+ssid, tmp, bssid_set, bssid=nil, nil, nil, nil
+wifi.sta.getap(scan_cfg, 1, listap)
+
+```
+
+#### See also
+[`wifi.sta.getip()`](#wifistagetip)
+
+## wifi.sta.getbroadcast()
+
+Gets the broadcast address in station mode.
+
+#### Syntax
+`wifi.sta.getbroadcast()`
+
+#### Parameters
+`nil`
+
+#### Returns
+broadcast address as string, for example "192.168.0.255", 
+returns `nil` if IP address = "0.0.0.0".
+
+#### See also
+[`wifi.sta.getip()`](#wifistagetip)
+
+## wifi.sta.getconfig()
+
+Gets the WiFi station configuration. 
+
+#### Syntax
+`wifi.sta.getconfig()`
+
+#### Parameters
+none
+
+#### Returns
+ssid, password, bssid_set, bssid
+
+Note: If bssid_set is equal to 0 then bssid is irrelevant 
+
+#### Example
+
+```lua
+--Get current Station configuration
+ssid, password, bssid_set, bssid=wifi.sta.getconfig()
+print("\nCurrent Station configuration:\nSSID : "..ssid
+.."\nPassword  : "..password
+.."\nBSSID_set  : "..bssid_set
+.."\nBSSID: "..bssid.."\n")
+ssid, password, bssid_set, bssid=nil, nil, nil, nil
+```
+
+#### See also
+- [`wifi.sta.connect()`](#wifistaconnect)
+- [`wifi.sta.disconnect()`](#wifistadisconnect)
+
+## wifi.sta.gethostname()
+
+Gets current station hostname.
+
+#### Syntax
+`wifi.sta.gethostname()`
+
+#### Parameters
+none
+
+#### Returns
+currently configured hostname
+
+#### Example
+```lua
+print("Current hostname is: \""..wifi.sta.gethostname().."\"")
+```
+
+## wifi.sta.getip()
+
+Gets IP address, netmask, and gateway address in station mode.
+
+#### Syntax
+`wifi.sta.getip()`
+
+#### Parameters
+none
+
+#### Returns
+IP address, netmask, gateway address as string, for example "192.168.0.111". Returns `nil` if IP = "0.0.0.0".
+
+#### Example
+```lua
+-- print current IP address, netmask, gateway
+print(wifi.sta.getip())
+-- 192.168.0.111  255.255.255.0  192.168.0.1
+ip = wifi.sta.getip()
+print(ip)
+-- 192.168.0.111
+ip, nm = wifi.sta.getip()
+print(nm)
+-- 255.255.255.0
+```
+
+#### See also
+[`wifi.sta.getmac()`](#wifistagetmac)
+
+## wifi.sta.getmac()
+
+Gets MAC address in station mode.
+
+#### Syntax
+`wifi.sta.getmac()`
+
+#### Parameters
+none
+
+#### Returns
+MAC address as string e.g. "18-33-44-FE-55-BB"
+
+#### See also
+[`wifi.sta.getip()`](#wifistagetip)
+
+## wifi.sta.sethostname()
+
+Sets station hostname.
+
+#### Syntax
+`wifi.sta.sethostname(hostname)`
+
+#### Parameters
+`hostname` must only contain letters, numbers and hyphens('-') and be 32 characters or less with first and last character being alphanumeric
+
+#### Returns
+true if hostname was successfully set, false otherwise
+
+#### Example
+```lua
+if (wifi.sta.sethostname("NodeMCU") == true) then
+	print("hostname was successfully changed")
+else
+	print("hostname was not changed")
+end
+```
+
+## wifi.sta.setip()
+Sets IP address, netmask, gateway address in station mode.
+
+#### Syntax
+`wifi.sta.setip(cfg)`
+
+#### Parameters
+`cfg` table contain IP address, netmask, and gateway
+```lua
+{
+  ip = "192.168.0.111",
+  netmask = "255.255.255.0",
+  gateway = "192.168.0.1"
+}
+```
+
+#### Returns
+true if success, false otherwise
+
+#### See also
+[`wifi.sta.setmac()`](#wifistasetmac)
+
+## wifi.sta.setmac()
+
+Sets MAC address in station mode.
+
+#### Syntax
+`wifi.sta.setmac(mac)`
+
+#### Parameters
+MAC address in string e.g. "DE:AD:BE:EF:7A:C0"
+
+#### Returns
+true if success, false otherwise
+
+#### Example
+```lua
+print(wifi.sta.setmac("DE:AD:BE:EF:7A:C0"))
+```
+
+#### See also
+[`wifi.sta.setip()`](#wifistasetip)
+
+## wifi.sta.status()
+
+Gets the current status in station mode.
+
+#### Syntax
+`wifi.sta.status()`
+
+#### Parameters
+`nil`
+
+#### Returns
+number: 0~5
+
+- 0: STATION_IDLE,
+- 1: STATION_CONNECTING,
+- 2: STATION_WRONG_PASSWORD,
+- 3: STATION_NO_AP_FOUND,
+- 4: STATION_CONNECT_FAIL,
+- 5: STATION_GOT_IP.
+
+# wifi.ap Module
+
+## wifi.ap.config()
+
+Sets SSID and password in AP mode. Be sure to make the password at least 8 characters long! If you don't it will default to *no* password and not set the SSID! It will still work as an access point but use a default SSID like e.g. ESP_9997C3.
+
+#### Syntax
+`wifi.ap.config(cfg)`
+
+#### Parameters
+- `ssdi` SSID chars 1-32
+- `pwd` password chars 8-64
+- `auth` authentication  one of AUTH\_OPEN, AUTH\_WPA\_PSK, AUTH\_WPA2\_PSK, AUTH\_WPA\_WPA2\_PSK, default = AUTH\_OPEN
+- `channel` channel number 1-14 default = 6
+- `hidden` 0 = not hidden, 1 = hidden, default 0
+- `max` maximal number of connections 1-4 default=4
+- `beacon` beacon interval time in range 100-60000, default = 100
+
+#### Returns
+`nil`
+
+#### Example:
+```lua
+ cfg={}
+ cfg.ssid="myssid"
+ cfg.pwd="mypassword"
+ wifi.ap.config(cfg)
+```
+
+## wifi.ap.getbroadcast()
+
+Gets broadcast address in AP mode.
+
+#### Syntax
+`wifi.ap.getbroadcast()`
+
+#### Parameters
+none
+
+#### Returns
+broadcast address in string, for example "192.168.0.255", 
+returns `nil` if IP address = "0.0.0.0".
+
+#### Example
+```lua
+bc = wifi.ap.getbroadcast()
+print(bc)
+-- 192.168.0.255
+```
+
+#### See also
+[`wifi.ap.getip()`](#wifiapgetip)
+
+## wifi.ap.getclient()
+
+Gets table of clients connected to device in AP mode.
+
+#### Syntax
+`wifi.ap.getclient()`
+
+#### Parameters
+none
+
+#### Returns
+table of connected clients
+
+#### Example
+```lua
+table={}
+table=wifi.ap.getclient()
+for mac,ip in pairs(table) do
+	print(mac,ip)
+end
+
+-- or shorter
+for mac,ip in pairs(wifi.ap.getclient()) do
+	print(mac,ip)
+end
+```
+
+## wifi.ap.getip()
+
+Gets IP address, netmask and gateway in AP mode.
+
+#### Syntax
+`wifi.ap.getip()`
+
+#### Parameters
+none
+
+#### Returns
+IP address, netmask, gateway address as string, for example "192.168.0.111", returns `nil` if IP address = "0.0.0.0".
+
+#### Example
+
+```lua
+-- print current ip, netmask, gateway
+print(wifi.ap.getip())
+-- 192.168.4.1  255.255.255.0  192.168.4.1
+ip = wifi.ap.getip()
+print(ip)
+-- 192.168.4.1
+ip, nm = wifi.ap.getip()
+print(nm)
+-- 255.255.255.0
+ip, nm, gw = wifi.ap.getip()
+print(gw)
+-- 192.168.4.1
+```
+
+#### See also
+- [`wifi.ap.getmac()`](#wifiapgetmac)
+
+## wifi.ap.getmac()
+
+Gets MAC address in AP mode.
+
+#### Syntax
+`wifi.ap.getmac()`
+
+#### Parameters
+none
+
+#### Returns
+MAC address as string, for example "1A-33-44-FE-55-BB"
+
+#### See also
+[`wifi.ap.getip()`](#wifiapgetip)
+
+## wifi.ap.setip()
+
+Sets IP address, netmask and gateway address in AP mode.
+
+#### Syntax
+`wifi.ap.setip(cfg)`
+
+#### Parameters
+`cfg` table contain IP address, netmask, and gateway
+
+#### Returns
+true if successful, false otherwise
+
+#### Example
+
+```lua
+cfg =
+{
+	ip="192.168.1.1",
+	netmask="255.255.255.0",
+	gateway="192.168.1.1"
+}
+wifi.ap.setip(cfg)
+```
+
+#### See also
+[`wifi.ap.setmac()`](#wifiapsetmac)
+
+## wifi.ap.setmac()
+
+Sets MAC address in AP mode.
+
+#### Syntax
+`wifi.ap.setmac(mac)`
+
+#### Parameters
+MAC address in byte string, for example "AC-1D-1C-B1-0B-22"
+
+#### Returns
+true if success, false otherwise
+
+#### Example
+```lua
+print(wifi.ap.setmac("AC-1D-1C-B1-0B-22"))
+```
+
+#### See also
+[`wifi.ap.setip()`](#wifiapsetip)
+
+# wifi.ap.dhcp Module
+
+## wifi.ap.dhcp.config()
+
+Configure the dhcp service. Currently only supports setting the start address of the dhcp address pool.
+
+#### Syntax
+`wifi.ap.dhcp.config(dhcp_config)`
+
+#### Parameters
+`dhcp_config` table containing the start-IP of the DHCP address pool, eg. "192.168.1.100"
+
+#### Returns
+`pool_startip`, `pool_endip`
+
+#### Example
+```lua
+dhcp_config ={}
+dhcp_config.start = "192.168.1.100"
+wifi.ap.dhcp.config(dhcp_config)
+```
+
+## wifi.ap.dhcp.start()
+
+Starts the DHCP service.
+
+#### Syntax
+`wifi.ap.dhcp.start()`
+
+#### Parameters
+none
+
+#### Returns
+boolean indicating success
+
+## wifi.ap.dhcp.stop()
+
+Stops the DHCP service.
+
+#### Syntax
+`wifi.ap.dhcp.stop()`
+
+#### Parameters
+none
+
+#### Returns
+boolean indicating success

+ 37 - 0
docs/en/modules/ws2801.md

@@ -0,0 +1,37 @@
+# WS2801 Module
+
+## ws2801.init()
+Initializes the module and sets the pin configuration.
+
+#### Syntax
+`ws2801.init(pin_clk, pin_data)`
+
+#### Parameters
+- `pin_clk` pin for the clock. Supported are GPIO 0, 2, 4, 5.
+- `pin_data` pin for the data. Supported are GPIO 0, 2, 4, 5.
+
+#### Returns
+`nil`
+
+## ws2801.write()
+Sends a string of RGB Data in 24 bits to WS2801. Don't forget to call `ws2801.init()` before.
+
+#### Syntax
+`ws2801.write(string)`
+
+####Parameters
+- `string` payload to be sent to one or more WS2801.
+  It should be composed from an RGB triplet per element.
+    - `R1` the first pixel's red channel value (0-255)
+    - `G1` the first pixel's green channel value (0-255)
+    - `B1` the first pixel's blue channel value (0-255)<br />
+    ... You can connect a lot of WS2801...
+    - `R2`, `G2`, `B2` are the next WS2801's Red, Green, and Blue channel values
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+ws2801.write(string.char(255,0,0, 0,255,0, 0,0,255))
+```

+ 53 - 0
docs/en/modules/ws2812.md

@@ -0,0 +1,53 @@
+# WS2812 Module
+
+## ws2812.write()
+Send GRB data in 8 bits to a WS2812 chain.
+
+#### Syntax
+`ws2812.writegrb(pin, string)`
+
+#### Parameters
+- `pin` any GPIO pin 0, 1, 2, ...
+- `string` payload to be sent to one or more WS2812 LEDs.
+  It should be composed from a GRB triplet per element.
+    - `G1` the first pixel's Green channel (0-255)
+    - `R1` the first pixel's Red channel (0-255)
+    - `B1` the first pixel's Blue channel (0-255)<br />
+    ... You can connect a lot of WS2812 ...
+    - `G2`, `R2`, `B2` are the next WS2812's Green, Red, and Blue channel parameters
+
+#### Returns
+`nil`
+
+```lua
+g = 0
+r = 255
+b = 0
+leds_grb = string.char(g,r,b, g,r,b) 
+ws2812.write(2, leds_grb) -- turn two WS2812Bs to red, connected to pin 2
+```
+
+## ws2812.writergb()
+Send GRB data in 8bits to a WS2812 chain.
+
+#### Syntax
+`ws2812.writergb(pin, string)`
+
+#### Parameters
+- `pin` any GPIO pin 0, 1, 2, ...
+- `string` payload to be sent to one or more WS2812 LEDs.
+  It should be composed from an RGB triplet per element.
+    - `R1` the first pixel's Red channel (0-255)
+    - `G1` the first pixel's Green channel (0-255)
+    - `B1` the first pixel's Blue channel (0-255)<br />
+    ... You can connect a lot of WS2812 ...
+    - `R2`, `G2`, `B2` are the next WS2812's Red, Green, and Blue channel parameters
+
+#### Returns
+`nil`
+
+#### Example
+```lua
+leds_rgb = string.char(255,0,0, 0,255,0, 0,0,255) 
+ws2812.writergb(2, leds_rgb) -- turn three WS2812Bs to red, green, and blue respectively
+```

+ 5 - 0
docs/en/start.md

@@ -0,0 +1,5 @@
+# Getting started
+## Obtain the firmware
+[Build the firmware](build.html) or download it from ?
+## Flash the firmware
+There are a number of tools for flashing the firmware.

+ 7 - 0
docs/en/support.md

@@ -0,0 +1,7 @@
+The [issues list on GitHub](https://github.com/nodemcu/nodemcu-firmware/issues) is **not** the right place to ask for help. Use it to report bugs and to place feature requests. Questions like "how do I ..." or "I can't get this to work ..." should be directed to StackOverflow or esp8266.com.
+
+## StackOverflow
+StackOverflow is the perfect place to ask coding questions. Use one or several of the following tags: [esp8266](http://stackoverflow.com/tags/esp8266), [nodemcu](http://stackoverflow.com/tags/nodemcu) or [Lua](http://stackoverflow.com/tags/lua).
+
+## esp8266.com Forums
+esp8266.com has a few [NodeMCU specific forums](http://www.esp8266.com/viewforum.php?f=17) where a number of our active community members tend to hang out.

+ 35 - 0
docs/en/upload.md

@@ -0,0 +1,35 @@
+As with [flashing](flash.md) there are several ways to upload code from your computer to the device.
+
+# ESPlorer
+
+> The essential multiplatforms tools for any ESP8266 developer from luatool author’s, including Lua for NodeMCU and MicroPython. Also, all AT commands are supported. Requires Java (Standard Edition - SE ver 7 and above) installed.
+
+![ESPlorer](../img/ESPlorer.jpg "ESPlorer")
+
+Source: https://github.com/4refr0nt/ESPlorer
+
+Supported platforms: OS X, Linux, Windows, anything that runs Java
+
+# nodemcu-uploader.py
+
+> A simple tool for uploading files to the filesystem of an ESP8266 running NodeMCU as well as some other useful commands.
+
+Source: https://github.com/kmpm/nodemcu-uploader
+
+Supported platforms: OS X, Linux, Windows, anything that runs Python
+
+# NodeMCU Studio
+
+> THIS TOOL IS IN REALLY REALLY REALLY REALLY EARLY STAGE!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+Source: https://github.com/nodemcu/nodemcu-studio-csharp
+
+Supported platforms: Windows
+
+# luatool
+
+> Allow easy uploading of any Lua-based script into the ESP8266 flash memory with NodeMcu firmware
+
+Source: https://github.com/4refr0nt/luatool
+
+Supported platforms: OS X, Linux, Windows, anything that runs Python

BIN
docs/img/ESPlorer.jpg


BIN
docs/img/enduser-setup.jpg


BIN
docs/img/favicon.png


BIN
docs/img/logo-small.png


BIN
docs/img/logo.png


+ 15 - 0
docs/index.md

@@ -0,0 +1,15 @@
+# NodeMCU Documentation
+
+NodeMCU is an [eLua](http://www.eluaproject.net/) based firmware for the [ESP8266 WiFi SOC from Espressif](http://espressif.com/en/products/esp8266/).  The NodeMCU *firmware* is a companion project to the popular [NodeMCU dev kits](https://github.com/nodemcu/nodemcu-devkit-v1.0), ready-made open source development boards with ESP8266-12E chips.
+
+## Up-To-Date Documentation
+At the moment the only up-to-date documentation maintained by the current NodeMCU team is in [English](en/index.md). It is part of the source code repository (`/docs` subfolder) and kept in sync with the code.
+
+We encourage you to help transferring the outdated translations (see below) into the repository.
+
+## Outdated And Sparse Documentation
+The following translations are based on outdated documentation, use them with caution. The links point to the [NodeMCU wiki on GitHub](https://github.com/nodemcu/nodemcu-firmware/wiki).
+
+- Chinese, [中文](https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_cn)
+- Russian, [русский](https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_ru)
+- Spanish, [español](https://github.com/nodemcu/nodemcu-firmware/wiki/nodemcu_api_es)

+ 158 - 0
docs/js/extra.js

@@ -0,0 +1,158 @@
+var nodemcu = nodemcu || {};
+(function () {
+  'use strict';
+  //var languageCodeToNameMap = {en: 'English', de: 'Deutsch'};
+  var languageCodeToNameMap = {en: 'English'};
+  var languageNames = values(languageCodeToNameMap);
+  var defaultLanguageCode = 'en';
+
+  $(document).ready(function () {
+    addToc();
+    hideNavigationForAllButSelectedLanguage();
+    addLanguageSelectorToRtdFlyOutMenu();
+  });
+
+  /**
+   * Adds a TOC-style table to each page in the 'Modules' section.
+   */
+  function addToc() {
+    var func, intro, tocHtmlTable;
+    if (isModulePage()) {
+      tocHtmlTable = '<table class="docutils">';
+      $('h2').each(function (index) {
+        // 'slice' cuts off the single permalink character at the end of the text (e.g. '¶')
+        func = $(this).text().slice(0, -1);
+        // get the first sentence of the paragraph directly below h2
+        intro = $(this).next().text();
+        intro = intro.substring(0, intro.indexOf('.') + 1);
+        tocHtmlTable += createTocTableRow(func, intro);
+      });
+      tocHtmlTable += '</table>';
+      $(tocHtmlTable).insertBefore($('h2').first())
+    }
+    function isModulePage() {
+      // if the breadcrumb contains 'Modules »' it must be an API page
+      return $("ul.wy-breadcrumbs li:contains('Modules »')").size() > 0;
+    }
+    function createTocTableRow(func, intro) {
+      // fragile attempt to auto-create the in-page anchor
+      var href = func.replace(/\.|:/g, '').replace('()', '').replace(' --', '-').replace(/ /g, '-');
+      var link = '<a href="#' + href.toLowerCase() + '">' + func + '</a>';
+      return '<tr><td>' + link + '</td><td>' + intro + '</td></tr>';
+    }
+  }
+
+  function hideNavigationForAllButSelectedLanguage() {
+    var selectedLanguageCode = determineSelectedLanguageCode();
+    var selectedLanguageName = languageCodeToNameMap[selectedLanguageCode];
+    // Finds all subnav elements and hides them if they're /language/ subnavs. Hence, all 'Modules' subnav elements
+    // won't be hidden.
+    // <ul class="subnav">
+    //   <li><span>Modules</span></li>
+    //   <li class="toctree-l1 ">
+    //     <a class="" href="EN/modules/node/">node</a>
+    //   </li>
+    $('.subnav li span').not(':contains(' + selectedLanguageName + ')').each(function (index) {
+      var spanElement = $(this);
+      if ($.inArray(spanElement.text(), languageNames) > -1) {
+        spanElement.parent().parent().hide();
+      }
+    });
+  }
+
+  /**
+   * Adds a language selector to the RTD fly-out menu found bottom left. Example:
+   *
+   * <dl>
+   *   <dt>Languages</dt>
+   *   <dd><a href="http://nodemcu.readthedocs.org/en/<branch>/de/">de</a></dd>
+   *   <strong>
+   *     <dd><a href="http://nodemcu.readthedocs.org/en/<branch>/en/">en</a></dd>
+   *   </strong>
+   * </dl>
+   *
+   * UGLY! That fly-out menu is added by RTD with an AJAX call after page load. Hence, we need to
+   * react to the subsequent DOM manipulation using a DOM4 MutationObserver. The provided structure
+   * is as follows:
+   *
+   * <div class="rst-other-versions">
+   *   <!-- Inserted RTD Footer -->
+   *   <div class="injected">
+   */
+  function addLanguageSelectorToRtdFlyOutMenu() {
+    var flyOutWrapper = $('.rst-other-versions');
+    // only relevant on RTD
+    if (flyOutWrapper.size() > 0) {
+      var observer = new MutationObserver(function (mutations) {
+        // since mutation on the target node was triggered we can safely assume the injected RTD div has now been added
+        var injectedDiv = $('.rst-other-versions .injected');
+        var selectedLanguageCode = determineSelectedLanguageCode();
+        var dl = document.createElement('dl');
+        var dt = document.createElement('dt');
+        dl.appendChild(dt);
+        dt.appendChild(document.createTextNode('Languages'));
+        for (var languageCode in languageCodeToNameMap) {
+          dl.appendChild(createLanguageLinkFor(languageCode, selectedLanguageCode === languageCode));
+        }
+        injectedDiv.prepend(dl);
+        // no need for that observer anymore
+        observer.disconnect();
+      });
+
+      // observed target node is the fly-out wrapper, the only event we care about is when children are modified
+      observer.observe(flyOutWrapper[0], {childList: true});
+    }
+  }
+
+  function createLanguageLinkFor(languageCode, isCurrentlySelected) {
+    var strong;
+    // split[0] is an '' because the path starts with the separator
+    var pathSegments = window.location.pathname.split('/');
+    var dd = document.createElement("dd");
+    var href = document.createElement("a");
+    href.setAttribute('href', '/' + pathSegments[1] + '/' + pathSegments[2] + '/' + languageCode);
+    href.appendChild(document.createTextNode(languageCode));
+    dd.appendChild(href);
+    if (isCurrentlySelected) {
+      strong = document.createElement("strong");
+      strong.appendChild(dd);
+      return strong;
+    } else {
+      return dd;
+    }
+  }
+
+  /**
+   * Analyzes the URL of the current page to find out what the selected language is. It's usually
+   * part of the location path. The code needs to distinguish between running MkDocs standalone
+   * and docs served from RTD. If no valid language could be determined the default language is
+   * returned.
+   *
+   * @returns 2-char language code
+   */
+  function determineSelectedLanguageCode() {
+    var selectedLanguageCode, path = window.location.pathname;
+    if (window.location.origin.indexOf('readthedocs') > -1) {
+      // path is like /en/<branch>/<lang>/build/ -> extract 'lang'
+      // split[0] is an '' because the path starts with the separator
+      selectedLanguageCode = path.split('/')[3];
+    } else {
+      // path is like /<lang>/build/ -> extract 'lang'
+      selectedLanguageCode = path.substr(1, 2);
+    }
+    if (!selectedLanguageCode || selectedLanguageCode.length > 2) {
+      selectedLanguageCode = defaultLanguageCode;
+    }
+    return selectedLanguageCode;
+  }
+
+  function values(associativeArray) {
+    var values = [];
+    for (var key in associativeArray) {
+      if (associativeArray.hasOwnProperty(key)) {
+        values.push(associativeArray[key]);
+      }
+    }
+    return values;
+  }
+}());

+ 65 - 0
mkdocs.yml

@@ -0,0 +1,65 @@
+site_name: NodeMCU Documentation
+site_description: Description of the NodeMCU documentation
+repo_url: https://github.com/nodemcu/nodemcu-firmware/
+
+theme: readthedocs
+strict: true
+
+markdown_extensions:
+#http://pythonhosted.org/Markdown/extensions/admonition.html
+- admonition:
+- toc:
+    permalink: True
+
+#requird due to https://github.com/rtfd/readthedocs.org/issues/1313
+#see http://mkdocs.readthedocs.org/en/latest/user-guide/styling-your-docs/#customising-a-theme
+extra_css:
+- css/extra.css
+extra_javascript:
+- js/extra.js
+
+site_favicon: img/favicon.png
+
+pages:
+- Overview: 'index.md'
+- English:
+    - Home: 'en/index.md'
+    - Building the firmware: 'en/build.md'
+    - Flashing the firmware: 'en/flash.md'
+    - Uploading code: 'en/upload.md'
+    - FAQ: 'en/faq.md'
+    - Support: 'en/support.md'
+    - Modules:
+        - 'adc': 'en/modules/adc.md'
+        - 'bit': 'en/modules/bit.md'
+        - 'bmp085': 'en/modules/bmp085.md'
+        - 'cjson': 'en/modules/cjson.md'
+        - 'coap': 'en/modules/coap.md'
+        - 'crypto': 'en/modules/crypto.md'
+        - 'dht': 'en/modules/dht.md'
+        - 'enduser setup': 'en/modules/enduser-setup.md'
+        - 'file': 'en/modules/file.md'
+        - 'gpio': 'en/modules/gpio.md'
+        - 'http': 'en/modules/http.md'
+        - 'hx711' : 'en/modules/hx711.md'
+        - 'i2c' : 'en/modules/i2c.md'
+        - 'mqtt': 'en/modules/mqtt.md'
+        - 'net': 'en/modules/net.md'
+        - 'node': 'en/modules/node.md'
+        - 'ow (1-Wire)': 'en/modules/ow.md'
+        - 'pwm' : 'en/modules/pwm.md'
+        - 'rtcmem': 'en/modules/rtcmem.md'
+        - 'rtctime': 'en/modules/rtctime.md'
+        - 'rtcfifo': 'en/modules/rtcfifo.md'
+        - 'sntp': 'en/modules/sntp.md'
+        - 'spi': 'en/modules/spi.md'
+        - 'tmr': 'en/modules/tmr.md'
+        - 'tsl2561': 'en/modules/tsl2561.md'
+        - 'u8g': 'en/modules/u8g.md'
+        - 'uart': 'en/modules/uart.md'
+        - 'ucg': 'en/modules/ucg.md'
+        - 'wifi': 'en/modules/wifi.md'
+        - 'ws2801': 'en/modules/ws2801.md'
+        - 'ws2812': 'en/modules/ws2812.md'
+#- Deutsch:
+#    - Home: 'de/index.md'

Деякі файли не було показано, через те що забагато файлів було змінено