Commit be047ff7 authored by Marcel Stör's avatar Marcel Stör
Browse files

Merge branch 'dev', 1.5.4.1 master drop

parents b580bfe7 a8d984ae
......@@ -5,9 +5,9 @@
Basic HTTP *client* module that provides an interface to do 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 by available memory. Attempting to receive pages larger than this will fail. If larger page/body sizes are necessary, consider using [`net.createConnection()`](net.md#netcreateconnection) and stream in the data.
!!! note "Note:"
!!! attention
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 behavior.
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 behavior. Use [`node.task.post()`](https://nodemcu.readthedocs.io/en/master/en/modules/node/#nodetaskpost) in the callbacks of your calls to start subsequent calls if you want to chain them (see [#1258](https://github.com/nodemcu/nodemcu-firmware/issues/1258)).
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).
......
# L3G4200D Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2015-04-09 | [Jason Schmidlapp](https://github.com/jschmidlapp) | [Jason Schmidlapp](https://github.com/jschmidlapp) | [l3g4200d.c](../../../app/modules/l3g4200d.c)|
This module provides access to the [L3G4200D](https://www.sparkfun.com/products/10612) three axis digital gyroscope.
## l3g4200d.read()
Samples the sensor and returns the gyroscope output.
#### Syntax
`l3g4200d.read()`
#### Returns
X,Y,Z gyroscope output
#### Example
```lua
l3g4200d.init(1, 2)
local x,y,z = l3g4200d.read()
print(string.format("X = %d, Y = %d, Z = %d", x, y, z)
```
## l3g4200d.init()
Initializes the module and sets the pin configuration.
#### Syntax
`l3g4200d.init(sda, scl)`
#### Parameters
- `sda` data pin
- `scl` clock pin
#### Returns
`nil`
......@@ -90,7 +90,7 @@ 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:"
!!! caution
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.
......@@ -179,7 +179,7 @@ print("NodeMCU "..majorVer.."."..minorVer.."."..devVer)
Submits a string to the Lua interpreter. Similar to `pcall(loadstring(str))`, but without the single-line limitation.
!!! note "Note:"
!!! attention
This function only has an effect when invoked from a callback. Using it directly on the console **does not work**.
......@@ -252,7 +252,7 @@ node.led(0)
Redirects the Lua interpreter output to a callback function. Optionally also prints it to the serial console.
!!! note "Note:"
!!! caution
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.
......
# pcm module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2016-06-05 | [Arnim Läuger](https://github.com/devsaurus) | [Arnim Läuger](https://github.com/devsaurus) | [pcm.c](../../../app/modules/pcm.c)|
Play sounds through various back-ends.
## Sigma-Delta hardware
The ESP contains a sigma-delta generator that can be used to synthesize audio with the help of an external low-pass filter. All regular GPIOs (except GPIO0) are able to output the digital waveform, though there is only one single generator.
The external filter circuit is shown in the following schematic. Note that the voltage divider resistors limit the output voltage to 1&nbsp;V<sub>PP</sub>. This should match most amplifier boards, but cross-checking against your specific configuration is required.
![low-pass filter](../../img/sigma_delta_audiofilter.png "low-pass filter for sigma-delta driver")
!!! important
This driver shares hardware resources with other modules. Thus you can't operate it in parallel to the `sigma delta`, `perf`, or `pwm` modules. They require the sigma-delta generator and the hw_timer, respectively.
## Audio format
Audio is expected as a mono raw unsigned 8&nbsp;bit stream at sample rates between 1&nbsp;k and 16&nbsp;k samples per second. Regular WAV files can be converted with OSS tools like [Audacity](http://www.audacityteam.org/) or [SoX](http://sox.sourceforge.net/). Adjust the volume before the conversion.
```
sox jump.wav -r 8000 -b 8 -c 1 jump_8k.u8
```
Also see [play_file.lua](../../../lua_examples/pcm/play_file.lua) in the examples folder.
## pcm.new()
Initializes the audio driver.
### Sigma-Delta driver
#### Syntax
`pcm.new(pcm.SD, pin)`
#### Parameters
`pcm.SD` use sigma-delta hardware
- `pin` 1~10, IO index
#### Returns
Audio driver object.
# Audio driver sub-module
Each audio driver exhibits the same control methods for playing sounds.
## pcm.drv:close()
Stops playback and releases the audio hardware.
#### Syntax
`drv:close()`
#### Parameters
none
#### Returns
`nil`
## pcm.drv:on()
Register callback functions for events.
#### Syntax
`drv:on(event[, cb_fn[, freq]])`
#### Parameters
- `event` identifier, one of:
- `data` callback function is supposed to return a string containing the next chunk of data.
- `drained` playback was stopped due to lack of data. The last 2 invocations of the `data` callback didn't provide new chunks in time (intentionally or unintentionally) and the internal buffers were fully consumed.
- `paused` playback was paused by `pcm.drv:pause()`.
- `stopped` playback was stopped by `pcm.drv:stop()`.
- `vu` new peak data, `cb_fn` is triggered `freq` times per second (1 to 200 Hz).
- `cb_fn` callback function for the specified event. Unregisters previous function if omitted. First parameter is `drv`, followed by peak data for `vu` callback.
#### Returns
`nil`
## pcm.drv:play()
Starts playback.
#### Syntax
`drv:play(rate)`
#### Parameters
`rate` sample rate. Supported are `pcm.RATE_1K`, `pcm.RATE_2K`, `pcm.RATE_4K`, `pcm.RATE_5K`, `pcm.RATE_8K`, `pcm.RATE_10K`, `pcm.RATE_12K`, `pcm.RATE_16K` and defaults to `RATE_8K` if omitted.
#### Returns
`nil`
## pcm.drv:pause()
Pauses playback. A call to `drv:play()` will resume from the last position.
#### Syntax
`drv:pause()`
#### Parameters
none
#### Returns
`nil`
## pcm.drv:stop()
Stops playback and releases buffered chunks.
#### Syntax
`drv:stop()`
#### Parameters
none
#### Returns
`nil`
......@@ -9,7 +9,7 @@ The rtcfifo module implements a first-in,first-out storage intended for sensor r
- Values are limited to 16 bits of precision, but have a separate field for storing an E<sup>-n</sup> multiplier. This allows for high fidelity even when working with very small values. The effective range is thus 1E<sup>-7</sup> to 65535.
- Sensor names are limited to a maximum of 4 characters.
!!! note "Important:"
!!! important
This module uses two sets of RTC memory slots, 10-20 for its control block, and a variable number of slots for samples and sensor names. By default these span 32-127, but this is configurable. Slots are claimed when [`rtcfifo.prepare()`](#rtcfifoprepare) is called.
......
......@@ -15,7 +15,7 @@ To enable this module, it needs to be given a reference time at least once (via
Note that while the rtctime module can keep time across deep sleeps, it *will* lose the time if the module is unexpectedly reset.
!!! note "Important:"
!!! important
This module uses RTC memory slots 0-9, inclusive. As soon as [`rtctime.set()`](#rtctimeset) (or [`sntp.sync()`](sntp.md#sntpsync)) has been called these RTC memory slots will be used.
......@@ -67,6 +67,34 @@ For applications where it is necessary to take samples with high regularity, thi
rtctime.dsleep_aligned(5*1000000, 3*1000000)
```
## rtctime.epoch2cal()
Converts a Unix timestamp to calendar format. Neither timezone nor DST correction is performed - the result is UTC time.
#### Syntax
`rtctime.epoch2cal(timestamp)`
#### Parameters
`timestamp` seconds since Unix epoch
#### Returns
A table containing the fields:
- `year` 1970 ~ 2038
- `mon` month 1 ~ 12 in current year
- `day` day 1 ~ 31 in current month
- `hour`
- `min`
- `sec`
- `yday` day 1 ~ 366 in current year
- `wday` day 1 ~ 7 in current weak (Sunday is 1)
#### Example
```lua
tm = rtctime.epoch2cal(rtctime.get())
print(string.format("%04d/%02d/%02d %02d:%02d:%02d", tm["year"], tm["mon"], tm["day"], tm["hour"], tm["min"], tm["sec"]))
```
## rtctime.get()
Returns the current time. If current time is not available, zero is returned.
......@@ -114,4 +142,4 @@ Values very close to the epoch are not supported. This is a side effect of keepi
rtctime.set(1436430589, 0)
```
#### See also
[`sntp.sync()`](sntp.md#sntpsync)
\ No newline at end of file
[`sntp.sync()`](sntp.md#sntpsync)
......@@ -10,7 +10,9 @@ When compiled together with the [rtctime](rtctime.md) module it also offers seam
## sntp.sync()
Attempts to obtain time synchronization.
Attempts to obtain time synchronization.
For best results you may want to to call this periodically in order to compensate for internal clock drift. As stated in the [rtctime](rtctime.md) module documentation it's advisable to sync time after deep sleep and it's necessary to sync after module reset (add it to [`init.lua`](upload.md#initlua) after WiFi initialization).
#### Syntax
`sntp.sync([server_ip], [callback], [errcallback])`
......
......@@ -97,9 +97,9 @@ Refer to [Serial Peripheral Interface Bus](https://en.wikipedia.org/wiki/Serial_
- `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`
- `clock_div` SPI clock divider, f(SPI) = 80 MHz / `clock_div`, 1 .. n (0 defaults to divider 8)
- `duplex_mode` duplex mode
- `spi.HALFDUPLEX` (default when omitted)
- `spi.HALFDUPLEX` (default when omitted)
- `spi.FULLDUPLEX`
#### Returns
......
# Switec Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2016-06-26 |[Philip Gladstone](https://github.com/pjsg) | [Philip Gladstone](https://github.com/pjsg) | [switec.c](../../../app/modules/switec.c)|
This module controls a [Switec X.27](http://www.jukenswisstech.com/?page_id=103) (or compatible) instrument stepper motor. These are the
stepper motors that are used in modern automotive instrument clusters. They are incredibly cheap
and can be found at your favorite auction site or Chinese shopping site. There are varieties
which are dual axis -- i.e. have two stepper motors driving two concentric shafts so you
can mount two needles from the same axis.
These motors run off 5V (some may work off 3.3V). They draw under 20mA and are designed to be
driven directly from MCU pins. Since the nodemcu runs at 3.3V, a level translator is required.
An octal translator like the [74LVC4245A](http://www.nxp.com/products/discretes-and-logic/logic/voltage-level-translators/octal-dual-supply-translating-transceiver-3-state-based-on-pip-74lvc4245a:74LVC4245A) can perfom this translation. It also includes all the
protection diodes required.
These motors can be driven off three pins, with `pin2` and `pin3` being the same GPIO pin.
If the motor is directly connected to the MCU, then the current load is doubled and may exceed
the maximum ratings. If, however, a driver chip is being used, then the load on the MCU is negligible
and the same MCU pin can be connected to two driver pins. In order to do this, just specify
the same pin for `pin2` and `pin3`.
These motors do not have absolute positioning, but come with stops at both ends of the range.
The startup procedure is to drive the motor anti-clockwise until it is guaranteed that the needle
is on the step. Then this point can be set as zero. It is important not to let the motor
run into the endstops during normal operation as this will make the pointing inaccurate.
This module does not enforce any range limiting.
!!! important
This module uses the hardware timer interrupt and hence it cannot be used at the same time as the PWM module. Both modules can be compiled into the same firmware image, but an application can only use one. It may be possible for an application to alternate between `switec` and `pwm`, but care must be taken.
## switec.setup()
Initialize the nodemcu to talk to a switec X.27 or compatible instrument stepper motor. The default
slew rate is set so that it should work for most motors. Some motors can run at 600 degress per second.
#### Syntax
`switec.setup(channel, pin1, pin2, pin3, pin4 [, maxDegPerSec])`
#### Parameters
- `channel` The switec module supports three stepper motors. The channel is either 0, 1 or 2.
- `pin1` This is a GPIO number and connects to pin 1 on the stepper.
- `pin2` This is a GPIO number and connects to pin 2 on the stepper.
- `pin3` This is a GPIO number and connects to pin 3 on the stepper.
- `pin4` This is a GPIO number and connects to pin 4 on the stepper.
- `maxDegPerSec` (optional) This can set to limit the maximum slew rate. The default is 400 degrees per second.
#### Returns
Nothing. If the arguments are in error, or the operation cannot be completed, then an error is thrown.
##### Note
Once a channel is setup, it cannot be re-setup until the needle has stopped moving.
#### Example
```lua
switec.setup(0, 5, 6, 7, 8)
```
## switec.moveto()
Starts the needle moving to the specified position. If the needle is already moving, then the current
motion is cancelled, and the needle will move to the new position. It is possible to get a callback
when the needle stops moving. This is not normally required as multiple `moveto` operations can
be issued in quick succession. During the initial calibration, it is important. Note that the
callback is not guaranteed to be called -- it is possible that the needle never stops at the
target location before another `moveto` operation is triggered.
#### Syntax
`switec.moveto(channel, position[, stoppedCallback)`
#### Parameters
- `channel` The switec module supports three stepper motors. The channel is either 0, 1 or 2.
- `position` The position (number of steps clockwise) to move the needle. Typically in the range 0 to around 1000.
- `stoppedCallback` (optional) callback to be invoked when the needle stops moving.
#### Errors
The channel must have been setup, otherwise an error is thrown.
#### Example
```lua
switec.moveto(0, 1000, function ()
switec.moveto(0, 0)
end)
```
## switec.reset()
This sets the current position of the needle as being zero. The needle must be stationary.
#### Syntax
`switec.reset(channel)`
#### Parameters
- `channel` The switec module supports three stepper motors. The channel is either 0, 1 or 2.
#### Errors
The channel must have been setup and the needle must not be moving, otherwise an error is thrown.
## switec.getpos()
Gets the current position of the needle and whether it is moving.
#### Syntax
`switec.getpos(channel)`
#### Parameters
- `channel` The switec module supports three stepper motors. The channel is either 0, 1 or 2.
#### Returns
- `position` the current position of the needle
- `moving` 0 if the needle is stationary. 1 for clockwise, -1 for anti-clockwise.
## switec.close()
Releases the resources associated with the stepper.
#### Syntax
`switec.close(channel)`
#### Parameters
- `channel` The switec module supports three stepper motors. The channel is either 0, 1 or 2.
#### Errors
The needle must not be moving, otherwise an error is thrown.
## Calibration
In order to set the zero point correctly, the needle should be driven anti-clockwise until
it runs into the end stop. Then the zero point can be set. The value of -1000 is used as that is
larger than the range of the motor -- i.e. it drives anti-clockwise through the entire range and
onto the end stop.
switec.setup(0, 5,6,7,8)
calibration = true
switec.moveto(0, -1000, function()
switec.reset(0)
calibration = false
end)
Other `moveto` operations should not be performed while `calibration` is set.
# TM1829 Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2016-05-15 | [Sebastian Haas](https://github.com/sebi2k1) | [Sebastian Haas](https://github.com/sebi2k1) | [tm1829.c](../../../app/modules/tm1829.c)|
tm1829 is a library to handle led strips using Titan Micro tm1829
led controller.
The library uses any GPIO to bitstream the led control commands.
## tm1829.write()
Send data to a led strip using native chip format.
#### Syntax
`tm1829.write(string)`
#### Parameters
- `string` payload to be sent to one or more TM1829 leds.
#### Returns
`nil`
#### Example
```lua
tm1829.write(5, string.char(255,0,0,255,0,0)) -- turn the two first RGB leds to blue using GPIO 5
```
......@@ -45,7 +45,7 @@ The WiFi mode, as one of the `wifi.STATION`, `wifi.SOFTAP`, `wifi.STATIONAP` or
Gets WiFi physical mode.
#### Syntax
`wifi.getpymode()`
`wifi.getphymode()`
#### Parameters
none
......@@ -157,7 +157,7 @@ Intended for use with SmartConfig apps, such as Espressif's [Android & iOS app](
Only usable in `wifi.STATION` mode.
!!! note "Note:"
!!! important
SmartConfig is disabled by default and can be enabled by setting `WIFI_SMART_ENABLE` in [`user_config.h`](https://github.com/nodemcu/nodemcu-firmware/blob/dev/app/include/user_config.h#L96) before you build the firmware.
......@@ -626,7 +626,7 @@ Gets MAC address in station mode.
none
#### Returns
MAC address as string e.g. "18-33-44-FE-55-BB"
MAC address as string e.g. "18:fe:34:a2:d7:34"
#### See also
[`wifi.sta.getip()`](#wifistagetip)
......@@ -751,7 +751,7 @@ NOTE: SoftAP Configuration will be retained until changed even if device is turn
#### Parameters
- `ssid` 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
- `auth` authentication method, one of `wifi.OPEN` (default), `wifi.WPA_PSK`, `wifi.WPA2_PSK`, `wifi.WPA_WPA2_PSK`
- `channel` channel number 1-14 default = 6
- `hidden` 0 = not hidden, 1 = hidden, default 0
- `max` maximal number of connections 1-4 default=4
......@@ -1036,7 +1036,7 @@ T: Table returned by event.
- `SSID`: SSID of access point.
- `BSSID`: BSSID of access point.
- `channel`: The channel the access point is on.
- `wifi.eventmon.STA_DISCONNECT`: Station was disconnected from access point.
- `wifi.eventmon.STA_DISCONNECTED`: Station was disconnected from access point.
- `SSID`: SSID of access point.
- `BSSID`: BSSID of access point.
- `REASON`: See [wifi.eventmon.reason](#wifieventmonreason) below.
......
......@@ -7,26 +7,41 @@ ws2812 is a library to handle ws2812-like led strips.
It works at least on WS2812, WS2812b, APA104, SK6812 (RGB or RGBW).
The library uses UART1 routed on GPIO2 (Pin D4 on NodeMCU DEVKIT) to
generate the bitstream.
generate the bitstream. It can use UART0 routed to TXD0 as well to
handle two led strips at the same time.
## ws2812.init()
Initialize UART1 and GPIO2, should be called once and before write()
**WARNING**: In dual mode, you will loose access to the Lua's console
through the serial port (it will be reconfigured to support WS2812-like
protocol). If you want to keep access to Lua's console, you will have to
use an other input channel like a TCP server (see [example](https://github.com/nodemcu/nodemcu-firmware/blob/master/examples/telnet.lua))
## ws2812.init(mode)
Initialize UART1 and GPIO2, should be called once and before write().
Initialize UART0 (TXD0) too if `ws2812.MODE_DUAL` is set.
#### Parameters
none
- `mode` (optional) either `ws2812.MODE_SINGLE` (default if omitted) or `ws2812.MODE_DUAL`.
In `ws2812.MODE_DUAL` mode you will be able to handle two strips in parallel but will lose access
to Lua's serial console as it shares the same UART and PIN.
#### Returns
`nil`
## ws2812.write()
Send data to a led strip using its native format which is generally Green,Red,Blue for RGB strips
Send data to one or two led strip using its native format which is generally Green,Red,Blue for RGB strips
and Green,Red,Blue,White for RGBW strips.
#### Syntax
`ws2812.write(string)`
`ws2812.write(data1, [data2])`
#### Parameters
- `string` payload to be sent to one or more WS2812 like leds.
- `data1` payload to be sent to one or more WS2812 like leds through GPIO2
- `data2` (optional) payload to be sent to one or more WS2812 like leds through TXD0 (`ws2812.MODE_DUAL` mode required)
Payload type could be:
- `nil` nothing is done
- `string` representing bytes to send
- `ws2812.buffer` see [Buffer module](#buffer-module)
#### Returns
`nil`
......@@ -34,12 +49,22 @@ and Green,Red,Blue,White for RGBW strips.
#### Example
```lua
ws2812.init()
ws2812.write(string.char(255,0,0,255,0,0) -- turn the two first RGB leds to green
ws2812.write(string.char(255, 0, 0, 255, 0, 0)) -- turn the two first RGB leds to green
```
```lua
ws2812.init()
ws2812.write(string.char(0,0,0,255,0,0,0,255) -- turn the two first RGBW leds to white
ws2812.write(string.char(0, 0, 0, 255, 0, 0, 0, 255)) -- turn the two first RGBW leds to white
```
```lua
ws2812.init(ws2812.MODE_DUAL)
ws2812.write(string.char(255, 0, 0, 255, 0, 0), string.char(0, 255, 0, 0, 255, 0)) -- turn the two first RGB leds to green on the first strip and red on the second strip
```
```lua
ws2812.init(ws2812.MODE_DUAL)
ws2812.write(nil, string.char(0, 255, 0, 0, 255, 0)) -- turn the two first RGB leds to red on the second strip, do nothing on the first
```
# Buffer module
......@@ -51,11 +76,12 @@ For this purpose, the ws2812 library offers a read/write buffer.
#### Example
Led chaser with a RGBW strip
```lua
local i, b = 0, ws2812.newBuffer(300, 4); b:fill(0,0,0,0); tmr.alarm(0, 50, 1, function()
ws2812.init()
local i, buffer = 0, ws2812.newBuffer(300, 4); buffer:fill(0, 0, 0, 0); tmr.alarm(0, 50, 1, function()
i=i+1
b:fade(2)
b:set(i%b:size()+1, 0, 0, 0, 255)
b:write()
buffer:fade(2)
buffer:set(i%buffer:size()+1, 0, 0, 0, 255)
ws2812.write(buffer)
end)
```
......@@ -86,8 +112,11 @@ Return the value at the given position
#### Example
```lua
buffer:get(2) -- return the color of the second led
buffer = ws2812.newBuffer(32, 4)
print(buffer:get(1))
0 0 0 0
```
## ws2812.buffer:set()
Set the value at the given position
......@@ -96,15 +125,32 @@ Set the value at the given position
#### Parameters
- `index` position in the buffer (1 for the first led)
- `color` bytes of the color
- `color` payload of the color
Payload could be:
- `number, number, ...` you should pass as many arguments as `bytesPerLed`
- `table` should contains `bytesPerLed` numbers
- `string` should contains `bytesPerLed` bytes
#### Returns
`nil`
#### Example
```lua
buffer = ws2812.newBuffer(32, 3)
buffer:set(1, 255, 0, 0) -- set the first led green for a RGB strip
```
```lua
buffer = ws2812.newBuffer(32, 4)
buffer:set(1, {0, 0, 0, 255}) -- set the first led white for a RGBW strip
```
```lua
buffer = ws2812.newBuffer(32, 3)
buffer:set(1, string.char(255, 0, 0)) -- set the first led green for a RGB strip
```
## ws2812.buffer:size()
Return the size of the buffer in number of leds
......@@ -125,7 +171,7 @@ The number of given bytes must match the number of bytesPerLed of the buffer
`buffer:fill(color)`
#### Parameters
- `color` bytes of the color
- `color` bytes of the color, you should pass as many arguments as `bytesPerLed`
#### Returns
`nil`
......@@ -134,14 +180,16 @@ The number of given bytes must match the number of bytesPerLed of the buffer
```lua
buffer:fill(0, 0, 0) -- fill the buffer with black for a RGB strip
```
## ws2812.buffer:fade()
Divide each byte of each led by the given value. Useful for a fading effect
Fade in or out. Defaults to out. Multiply or divide each byte of each led with/by the given value. Useful for a fading effect.
#### Syntax
`buffer:fade(value)`
`buffer:fade(value [, direction])`
#### Parameters
- `value` value by which divide each byte
- `value` value by which to divide or multiply each byte
- `direction` ws2812.FADE\_IN or ws2812.FADE\_OUT. Defaults to ws2812.FADE\_OUT
#### Returns
`nil`
......@@ -149,16 +197,22 @@ Divide each byte of each led by the given value. Useful for a fading effect
#### Example
```lua
buffer:fade(2)
buffer:fade(2, ws2812.FADE_IN)
```
## ws2812.buffer:write()
Output the buffer to the led strip
## ws2812.buffer:shift()
Shift the content of the buffer in positive or negative direction. This allows simple animation effects.
#### Syntax
`buffer:write()`
`buffer:shift(value [, mode])`
#### Parameters
none
- `value` number of pixels by which to rotate the buffer. Positive values rotate forwards, negative values backwards.
- `mode` is the shift mode to use. Can be one of `ws2812.SHIFT_LOGICAL` or `ws2812.SHIFT_CIRCULAR`. In case of SHIFT\_LOGICAL, the freed pixels are set to 0 (off). In case of SHIFT\_CIRCULAR, the buffer is treated like a ring buffer, inserting the pixels falling out on one end again on the other end. Defaults to SHIFT\_LOGICAL.
#### Returns
`nil`
#### Example
```lua
buffer:shift(3)
```
# SPIFFS File System
The NodeMCU project uses the [SPIFFS](https://github.com/pellepl/spiffs)
filesystem to store files in the flash chip. The technical details about how this is configured can be found below, along with various build time options.
# spiffsimg - Manipulate SPI Flash File System disk images
Ever wished you could prepare a SPIFFS image offline and flash the whole
thing onto your microprocessor's storage instead of painstakingly upload
file-by-file through your app on the micro? With spiffsimg you can!
NodeMCU uses a SPIFFS filesystem that knows how big it is -- i.e. when you build a file system
image, it must fit into the flash chip, and it cannot be expanded once flashed.
It is important to give the `spiffimg` tool the correct size. You can provide either the `-c` option or both the `-U` and `-S` options.
### Syntax
```
spiffsimg -f <filename>
[-o <offsetfile>]
[-c <size>]
[-S <flashsize>]
[-U <usedsize>]
[-d]
[-l | -i | -r <scriptname> ]
```
### Supported operations:
* `-f` specifies the filename for the disk image. '%x' will be replaced by the calculated offset of the file system.
* `-o` specifies the file which is to contain the calculated offset.
* `-S` specifies the size of the flash chip. `32m` is 32 mbits, `1MB` is 1 megabyte.
* `-U` specifies the amount of flash used by the firmware. Decimal or Hex bytes.
* `-c` Create a blank disk image of the given size.
* `-l` List the contents of the given disk image.
* `-i` Interactive commands.
* `-r` Scripted commands from filename.
* `-d` causes the disk image to be deleted on error. This makes it easier to script.
### Available commands:
* `ls` List contents. Output format is {type} {size} {name}.
* `cat <filename>` Dump file contents to stdout.
* `rm <filename>` Delete file.
* `info` Display SPIFFS usage estimates.
* `import <srcfile> <spiffsname>` Import a file into the disk image.
* `export <spiffsname> <dstfile>` Export a file from the disk image.
### Example:
```lua
# spiffsimg -f flash.img -S 32m -U 524288 -i
> import myapp/lua/init.lua init.lua
> import myapp/lua/httpd.lua httpd.lua
> import myapp/html/index.html http/index.html
> import myapp/html/favicon.ico http/favicon.ico
> ls
f 122 init.lua
f 5169 httpd.lua
f 2121 http/index.html
f 880 http/favicon.ico
>^D
#
```
### Known limitations:
* The block & page sizes are hard-coded to be compatible with nodemcu.
* Error handling is not entirely consistent, some errors result in an
early exit, others just print an error (both cause a non-zero exit though).
* Only flat SPIFFS is supported.
# Technical Details
The SPIFFS configuration is 4k sectors (the only size supported by the SDK) and 8k blocks. 256 byte pages. Magic is enabled and magic_len is also enabled. This allows the firmware to find the start of the filesystem (and also the size).
One of the goals is to make the filsystem more persistent across reflashing of the firmware.
There are two significant sizes of flash -- the 512K and 4M (or bigger).
The file system has to start on a 4k boundary, but since it ends on a much bigger boundary (a 16k boundary), it also starts on an 8k boundary. For the small flash chip, there is
not much spare space, so a newly formatted file system will start as low as possible (to get as much space as possible). For the large flash, the
file system will start on a 64k boundary. A newly formatted file system will start between 64k and 128k from the end of the firmware. This means that the file
system will survive lots of reflashing and at least 64k of firmware growth.
The spiffsimg tool can also be built (from source) in the nodemcu-firmware build tree. If there is any data in the `local/fs` directory tree, then it will
be copied into the flash disk image. Two images will normally be created -- one for the 512k flash part and the other for the 4M flash part. If the data doesn't
fit into the 512k part after the firmware is included, then the file will not be generated.
The disk image file is placed into the `bin` directory and it is named `0x<offset>-<size>.bin` where the offset is the location where it should be
flashed, and the size is the size of the flash part. It is quite valid (and quicker) to flash the 512k image into a 4M part. However, there will probably be
limited space in the file system for creating new files.
If no file system is found during platform boot, then a new file system will be formatted. This can take some time on the first boot.
Note that the last 16k of the flash chip is reserved for the SDK to store parameters (such as the client wifi settings).
In order to speed up the boot time, it is possible to define (at build time) the size of the SPIFFS Filesystem to be formatted. This can be as small as 32768 bytes which gives a filesystem with about 15k bytes of usable space.
Just place the following define in `user_config.h` or some other file that is included during the build.
```
#define SPIFFS_MAX_FILESYSTEM_SIZE 32768
```
This filesystem size limit only affects the formatting of a file system -- if the firm finds an existing valid filesystem (of any size) it will use that. However, if the
filesystem is reformatted from Lua (using file.format()) then the new file system will obey the size limit.
There is also an option to control the positioning of the SPIFFS file system:
```
#define SPIFFS_FIXED_LOCATION 0x100000
```
This specifies that the SPIFFS filesystem starts at 1Mb from the start of the flash. Unless otherwise specified, it will run to the end of the flash (excluding the 16k of space reserved by the SDK).
There is an option that limits the size of the file system to run up to the next 1MB boundary (minus the 16k for the parameter space). This may be useful when dealing with OTA upgrades.
```
#define SPIFFS_SIZE_1M_BOUNDARY
```
As with [flashing](flash.md) there are several ways to upload code from your computer to the device.
Note that the NodeMCU serial interface uses 115200bps at boot time. To change the speed after booting, issue `uart.setup(0,9600,8,0,1,1)`. ESPlorer will do this automatically when changing the speed in the dropdown list. If the device panics and resets at any time, errors will be written to the serial interface at 115200 bps.
Note that the NodeMCU serial interface uses 115'200bps at boot time. To change the speed after booting, issue `uart.setup(0,9600,8,0,1,1)`. ESPlorer will do this automatically when changing the speed in the dropdown list. If the device panics and resets at any time, errors will be written to the serial interface at 115'200 bps.
# ESPlorer
# Tools
## 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.
......@@ -12,7 +14,7 @@ Source: [https://github.com/4refr0nt/ESPlorer](https://github.com/4refr0nt/ESPlo
Supported platforms: OS X, Linux, Windows, anything that runs Java
# nodemcu-uploader.py
## nodemcu-uploader.py
> A simple tool for uploading files to the filesystem of an ESP8266 running NodeMCU as well as some other useful commands.
......@@ -20,7 +22,7 @@ Source: [https://github.com/kmpm/nodemcu-uploader](https://github.com/kmpm/nodem
Supported platforms: OS X, Linux, Windows, anything that runs Python
# NodeMCU Studio
## NodeMCU Studio
> THIS TOOL IS IN REALLY REALLY REALLY REALLY EARLY STAGE!!!!!!!!!!!!!!!!!!!!!!!!!!!
......@@ -28,7 +30,7 @@ Source: [https://github.com/nodemcu/nodemcu-studio-csharp](https://github.com/no
Supported platforms: Windows
# luatool
## luatool
> Allow easy uploading of any Lua-based script into the ESP8266 flash memory with NodeMcu firmware
......@@ -36,21 +38,60 @@ Source: [https://github.com/4refr0nt/luatool](https://github.com/4refr0nt/luatoo
Supported platforms: OS X, Linux, Windows, anything that runs Python
# init.lua
You will see "lua: cannot open init.lua" printed to the serial console when the device boots after it's been freshly flashed. If NodeMCU finds a `init.lua` in the root of the file system it will execute it as part of the boot sequence (standard Lua feature). Hence, your application is initialized and triggered from `init.lua`. Usually you first set up the WiFi connection and only continue once that has been successful.
Be very careful not to lock yourself out! If there's a bug in your `init.lua` you may be stuck in an infinite reboot loop. It is, therefore, advisable to build a small delay into your startup sequence that would allow you to interrupt the sequence by e.g. deleting or renaming `init.lua` (see also [FAQ](lua-developer-faq.md#how-do-i-avoid-a-panic-loop-in-initlua)). Your `init.lua` is most likely going to be different than the one below but it's a good starting point for customizations:
```lua
-- load credentials, 'SSID' and 'PASSWORD' declared and initialize in there
dofile("credentials.lua")
function startup()
if file.open("init.lua") == nil then
print("init.lua deleted or renamed")
else
print("Running")
file.close("init.lua")
-- the actual application is stored in 'application.lua'
-- dofile("application.lua")
end
end
print("Connecting to WiFi access point...")
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID, PASSWORD)
-- wifi.sta.connect() not necessary because config() uses auto-connect=true by default
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip() == nil then
print("Waiting for IP address...")
else
tmr.stop(1)
print("WiFi connection established, IP address: " .. wifi.sta.getip())
print("You have 3 seconds to abort")
print("Waiting...")
tmr.alarm(0, 3000, 0, startup)
end
end)
```
Inspired by [https://github.com/ckuehnel/NodeMCU-applications](https://github.com/ckuehnel/NodeMCU-applications)
# Compiling Lua on your PC for Uploading
If you install lua on your development PC or Laptop then you can use the standard Lua
If you install `lua` on your development PC or Laptop then you can use the standard Lua
compiler to syntax check any Lua source before downloading it to the ESP8266 module. However,
the nodemcu compiler output uses different data types (e.g. it supports ROMtables) so the
the NodeMCU compiler output uses different data types (e.g. it supports ROMtables) so the
compiled output cannot run on the ESP8266.
Compiling source on one platform for use on another (e.g. Intel x38 Window to ESP8266) is
known as _cross-compilation_ and the nodemcu firmware supports the compilation of `luac.cross`
known as _cross-compilation_ and the NodeMCU firmware supports the compilation of `luac.cross`
on \*nix patforms which have Lua 5.1, the Lua filesystem module (lfs), and the essential
GCC tools. Simply change directory to the firmware root directoy and run the command:
GCC tools. Simply change directory to the firmware root directoy and run the command:
lua tools/cross-lua.lua
This will generate a `luac.cross` executable in your root directory which can be used to
compile and to syntax-check Lua source on the Development machine for execution under
nodemcu lua on the ESP8266.
NodeMCU Lua on the ESP8266.
......@@ -8,6 +8,7 @@ var nodemcu = nodemcu || {};
$(document).ready(function () {
addToc();
fixSearch();
hideNavigationForAllButSelectedLanguage();
addLanguageSelectorToRtdFlyOutMenu();
replaceRelativeLinksWithStaticGitHubUrl();
......@@ -43,6 +44,34 @@ var nodemcu = nodemcu || {};
}
}
/*
* RTD messes up MkDocs' search feature by tinkering with the search box defined in the theme, see
* https://github.com/rtfd/readthedocs.org/issues/1088. This function sets up a DOM4 MutationObserver
* to react to changes to the search form (triggered by RTD on doc ready). It then reverts everything
* the RTD JS code modified.
*/
function fixSearch() {
var target = document.getElementById('rtd-search-form');
var config = {attributes: true, childList: true};
var observer = new MutationObserver(function(mutations) {
// if it isn't disconnected it'll loop infinitely because the observed element is modified
observer.disconnect();
var form = $('#rtd-search-form');
form.empty();
form.attr('action', 'https://' + window.location.hostname + '/en/' + determineSelectedBranch() + '/search.html');
$('<input>').attr({
type: "text",
name: "q",
placeholder: "Search docs"
}).appendTo(form);
});
if (window.location.origin.indexOf('readthedocs') > -1) {
observer.observe(target, config);
}
}
function hideNavigationForAllButSelectedLanguage() {
var selectedLanguageCode = determineSelectedLanguageCode();
var selectedLanguageName = languageCodeToNameMap[selectedLanguageCode];
......@@ -173,7 +202,11 @@ var nodemcu = nodemcu || {};
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
branch = path.split('/')[2];
var thirdPathSegment = path.split('/')[2];
// 'latest' is an alias on RTD for the 'dev' branch - which is the default for 'branch' here
if (thirdPathSegment != 'latest') {
branch = thirdPathSegment;
}
}
return branch;
}
......
pwm.setup(0,500,50) pwm.setup(1,500,50) pwm.setup(2,500,50)
pwm.start(0) pwm.start(1) pwm.start(2)
function led(r,g,b) pwm.setduty(0,g) pwm.setduty(1,b) pwm.setduty(2,r) end
wifi.sta.autoconnect(1)
a=0
tmr.alarm( 1000,1,function() if a==0 then a=1 led(50,50,50) else a=0 led(0,0,0) end end)
sv:on("receive", function(s,c) s:send("<h1> Hello, world.</h1>") print(c) end )
sk=net.createConnection(net.TCP, 0)
sk:on("receive", function(sck, c) print(c) end )
sk:connect(80,"115.239.210.27")
sk:send("GET / HTTP/1.1\r\nHost: 115.239.210.27\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
sk:connect(80,"192.168.0.66")
sk:send("GET / HTTP/1.1\r\nHost: 192.168.0.66\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
i2c.setup(0,1,0,i2c.SLOW)
function read_bmp(addr) i2c.start(0) i2c.address(0,119,i2c.RECEIVER) c=i2c.read(0,1) i2c.stop(0) print(string.byte(c)) end
function read_bmp(addr) i2c.start(0) i2c.address(0,119,i2c.TRANSMITTER) i2c.write(0,addr) i2c.stop(0) i2c.start(0) i2c.address(0,119,i2c.RECEIVER) c=i2c.read(0,2) i2c.stop(0) return c end
s=net.createServer(net.TCP) s:listen(80,function(c) end)
ss=net.createServer(net.TCP) ss:listen(80,function(c) end)
s=net.createServer(net.TCP) s:listen(80,function(c) c:on("receive",function(s,c) print(c) end) end)
s=net.createServer(net.UDP)
s:on("receive",function(s,c) print(c) end)
s:listen(5683)
su=net.createConnection(net.UDP)
su:on("receive",function(su,c) print(c) end)
su:connect(5683,"192.168.18.101")
su:send("hello")
mm=node.list()
for k, v in pairs(mm) do print('file:'..k..' len:'..v) end
for k,v in pairs(d) do print("n:"..k..", s:"..v) end
gpio.mode(0,gpio.INT) gpio.trig(0,"down",function(l) print("level="..l) end)
t0 = 0;
function tr0(l) print(tmr.now() - t0) t0 = tmr.now()
if l==1 then gpio.trig(0,"down") else gpio.trig(0,"up") end end
gpio.mode(0,gpio.INT)
gpio.trig(0,"down",tr0)
su=net.createConnection(net.UDP)
su:on("receive",function(su,c) print(c) end)
su:connect(5001,"114.215.154.114")
su:send([[{"type":"signin","name":"nodemcu","password":"123456"}]])
su:send([[{"type":"signout","name":"nodemcu","password":"123456"}]])
su:send([[{"type":"connect","from":"nodemcu","to":"JYP","password":"123456"}]])
su:send("hello world")
s=net.createServer(net.TCP) s:listen(8008,function(c) c:on("receive",function(s,c) print(c) pcall(loadstring(c)) end) end)
s=net.createServer(net.TCP) s:listen(8008,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) c:on("receive",function(c,l) node.input(l) end) c:on("disconnection",function(c) con_std = nil node.output(nil) end) end)
s=net.createServer(net.TCP)
s:listen(23,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)
c:on("receive",function(c,l) node.input(l) end)
c:on("disconnection",function(c)
con_std = nil
node.output(nil)
end)
end)
srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive",function(conn,payload)
print(node.heap()) door="open" if gpio.read(8)==1 then door="open" else door="closed" end
conn:send("<h1> Door Sensor. The door is " .. door ..".</h1>") conn:close() end) end)
srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive",function(conn,payload)
print(node.heap()) print(adc.read(0)) door="open" if gpio.read(0)==1 then door="open" else door="closed" end
conn:send("<h1> Door Sensor. The door is " .. door ..".</h1>") end) conn:on("sent",function(conn) conn:close() end) end)
srv=net.createServer(net.TCP) srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(node.heap())
door="open"
if gpio.read(0)==1 then door="open" else door="closed" end
conn:send("<h1> Door Sensor. The door is " .. door ..".</h1>")
end)
conn:on("sent",function(conn) conn:close() end)
end)
port = 9999
hostip = "192.168.1.99"
sk=net.createConnection(net.TCP, false)
sk:on("receive", function(conn, pl) print(pl) end )
sk:connect(port, hostip)
file.remove("init.lua")
file.open("init.lua","w")
file.writeline([[print("Petes Tester 4")]])
file.writeline([[tmr.alarm(5000, 0, function() dofile("thelot.lua") end )]])
file.close()
file.remove("thelot.lua")
file.open("thelot.lua","w")
file.writeline([[tmr.stop()]])
file.writeline([[connecttoap = function (ssid,pw)]])
file.writeline([[print(wifi.sta.getip())]])
file.writeline([[wifi.setmode(wifi.STATION)]])
file.writeline([[tmr.delay(1000000)]])
file.writeline([[wifi.sta.config(ssid,pw)]])
file.writeline([[tmr.delay(5000000)]])
file.writeline([[print("Connected to ",ssid," as ",wifi.sta.getip())]])
file.writeline([[end]])
file.writeline([[connecttoap("MyHub","0011223344")]])
file.close()
s=net.createServer(net.UDP) s:listen(5683) s:on("receive",function(s,c) print(c) s:send("echo:"..c) end)
s:on("sent",function(s) print("echo donn") end)
sk=net.createConnection(net.UDP, 0) sk:on("receive", function(sck, c) print(c) end ) sk:connect(8080,"192.168.0.88")
sk:send("GET / HTTP/1.1\r\nHost: 192.168.0.88\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
srv=net.createServer(net.TCP, 5) srv:listen(80,function(conn) conn:on("receive",function(conn,payload)
print(node.heap()) print(adc.read(0)) door="open" if gpio.read(0)==1 then door="open" else door="closed" end
conn:send("<h1> Door Sensor. The door is " .. door ..".</h1>") end) end)
srv=net.createServer(net.TCP)
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
print(payload) print(node.heap())
conn:send("<h1> Hello, NodeMcu.</h1>")
end)
conn:on("sent",function(conn) conn:close() end)
end)
function startServer()
print("WIFI AP connected. Wicon IP:")
print(wifi.sta.getip())
sv=net.createServer(net.TCP,180)
sv:listen(8080,function(conn)
print("Wifi console connected.")
function s_output(str)
if(conn~=nil) then
conn:send(str)
end
end
node.output(s_output,0)
conn:on("receive",function(conn,pl)
node.input(pl)
if (conn==nil) then
print("conn is nil")
end
print("hello")
mycounter=0 srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive",function(conn,payload)
if string.find(payload,"?myarg=") then mycounter=mycounter+1
m="<br/>Value= " .. string.sub(payload,string.find(payload,"?myarg=")+7,string.find(payload,"HTTP")-2) else m="" end
conn:send("<h1> Hello, this is Pete's web page.</h1>How are you today.<br/> Count=" .. mycounter .. m .. "Heap=".. node.heap())
end) conn:on("sent",function(conn) conn:close() conn = nil end) end)
srv=net.createServer(net.TCP) srv:listen(80,function(conn) conn:on("receive",function(conn,payload)
conn:send("HTTP/1.1 200 OK\r\n") conn:send("Connection: close\r\n\r\n") conn:send("<h1> Hello, NodeMcu.</h1>")
print(node.heap()) conn:close() end) end)
conn=net.createConnection(net.TCP)
conn:dns("www.nodemcu.com",function(conn,ip) print(ip) print("hell") end)
function connected(conn) conn:on("receive",function(conn,payload)
conn:send("HTTP/1.1 200 OK\r\n") conn:send("Connection: close\r\n\r\n") conn:send("<h1> Hello, NodeMcu.</h1>")
print(node.heap()) conn:close() end) end
srv=net.createServer(net.TCP)
srv:on("connection",function(conn) conn:on("receive",function(conn,payload)
conn:send("HTTP/1.1 200 OK\r\n") conn:send("Connection: close\r\n\r\n") conn:send("<h1> Hello, NodeMcu.</h1>")
print(node.heap()) conn:close() end) end)
srv:listen(80)
-- sieve.lua
-- the sieve of Eratosthenes programmed with coroutines
-- typical usage: lua -e N=500 sieve.lua | column
-- generate all the numbers from 2 to n
function gen (n) return coroutine.wrap(function () for i=2,n do coroutine.yield(i) end end) end
-- filter the numbers generated by `g', removing multiples of `p'
function filter (p, g) return coroutine.wrap(function () for n in g do if n%p ~= 0 then coroutine.yield(n) end end end) end
N=N or 500 -- from command line
x = gen(N) -- generate primes up to N
while 1 do
local n = x() -- pick a number until done
if n == nil then break end
print(n) -- must be a prime number
x = filter(n, x) -- now remove its multiples
end
file.remove("mylistener.lua")
file.open("mylistener.lua","w")
file.writeline([[gpio2 = 9]])
file.writeline([[gpio0 = 8]])
file.writeline([[gpio.mode(gpio2,gpio.OUTPUT)]])
file.writeline([[gpio.write(gpio2,gpio.LOW)]])
file.writeline([[gpio.mode(gpio0,gpio.OUTPUT)]])
file.writeline([[gpio.write(gpio0,gpio.LOW)]])
file.writeline([[l1="0\n"]])
file.writeline([[l2="0\n"]])
file.writeline([[l3="0\n"]])
file.writeline([[l4="0\n"]])
file.writeline([[sv=net.createServer(net.TCP, 5) ]])
file.writeline([[sv:listen(4000,function(c)]])
file.writeline([[c:on("disconnection", function(c) print("Bye") end )]])
file.writeline([[c:on("receive", function(sck, pl) ]])
-- file.writeline([[print(pl) ]])
file.writeline([[if (pl=="GO1\n") then c:send(l1) ]])
file.writeline([[elseif pl=="GO2\n" then c:send(l2) ]])
file.writeline([[elseif pl=="GO3\n" then c:send(l3) ]])
file.writeline([[elseif pl=="GO4\n" then c:send(l4) ]])
file.writeline([[elseif pl=="YES1\n" then l1="1\n" c:send("OK\n") gpio.write(gpio2,gpio.HIGH) ]])
file.writeline([[elseif pl=="NO1\n" then l1="0\n" c:send("OK\n") gpio.write(gpio2,gpio.LOW) ]])
file.writeline([[elseif pl=="YES2\n" then l2="1\n" c:send("OK\n") gpio.write(gpio0,gpio.HIGH) ]])
file.writeline([[elseif pl=="NO2\n" then l2="0\n" c:send("OK\n") gpio.write(gpio0,gpio.LOW) ]])
file.writeline([[elseif pl=="YES3\n" then l3="1\n" c:send("OK\n") print(node.heap()) ]])
file.writeline([[elseif pl=="NO3\n" then l3="0\n" c:send("OK\n") print(node.heap()) ]])
file.writeline([[elseif pl=="YES4\n" then l4="1\n" c:send("OK\n") print(node.heap()) ]])
file.writeline([[elseif pl=="NO4\n" then l4="0\n" c:send("OK\n") print(node.heap()) ]])
file.writeline([[else c:send("0\n") print(node.heap()) ]])
file.writeline([[end]])
file.writeline([[end)]])
file.writeline([[end)]])
file.close()
file.remove("myli.lua") file.open("myli.lua","w")
file.writeline([[sv=net.createServer(net.TCP, 5) ]])
file.writeline([[sv:listen(4000,function(c)]])
file.writeline([[c:on("disconnection", function(c) print("Bye") end )]])
--file.writeline([[c:on("sent", function(c) c:close() end )]])
file.writeline([[c:on("receive", function(sck, pl) ]])
file.writeline([[sck:send("0\n") print(node.heap()) ]])
file.writeline([[end)]]) file.writeline([[end)]]) file.close()
sv=net.createServer(net.TCP, 50) sv:listen(4000,function(c) c:on("disconnection",function(c) print("Bye") end)
c:on("receive", function(sck, pl) sck:send("0\n") print(node.heap()) end) end)
sv=net.createServer(net.TCP, 5) sv:listen(4000,function(c) c:on("disconnection",function(c) print("Bye") end)
c:on("receive", function(sck, pl) sck:send("0\n") print(node.heap()) end) c:on("sent", function(sck) sck:close() end) end)
s=net.createServer(net.UDP)
s:on("receive",function(s,c) print(c) end)
s:listen(8888)
print("This is a long long long line to test the memory limit of nodemcu firmware\n")
collectgarbage("setmemlimit",8)
print(collectgarbage("getmemlimit"))
tmr.alarm(1,5000,1,function() print("alarm 1") end)
tmr.stop(1)
tmr.alarm(0,1000,1,function() print("alarm 0") end)
tmr.stop(0)
tmr.alarm(2,2000,1,function() print("alarm 2") end)
tmr.stop(2)
tmr.alarm(6,2000,1,function() print("alarm 6") end)
tmr.stop(6)
for k,v in pairs(_G.package.loaded) do print(k) end
for k,v in pairs(_G) do print(k) end
for k,v in pairs(d) do print("n:"..k..", s:"..v) end
a="pin=9"
t={}
for k, v in string.gmatch(a, "(%w+)=(%w+)") do t[k]=v end
print(t["pin"])
function switch() gpio.mode(4,gpio.OUTPUT) gpio.mode(5,gpio.OUTPUT) tmr.delay(1000000) print("hello world") end
tmr.alarm(0,10000,0,function () uart.setup(0,9600,8,0,1) end) switch()
sk=net.createConnection(net.TCP, 0) sk:on("receive", function(sck, c) print(c) end ) sk:connect(80,"www.nodemcu.com") sk:send("GET / HTTP/1.1\r\nHost: www.nodemcu.com\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
sk=net.createConnection(net.TCP, 0) sk:on("receive", function(sck, c) print(c) end )
sk:on("connection", function(sck) sck:send("GET / HTTP/1.1\r\nHost: www.nodemcu.com\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n") end ) sk:connect(80,"www.nodemcu.com")
sk=net.createConnection(net.TCP, 0) sk:on("receive", function(sck, c) print(c) end ) sk:connect(80,"115.239.210.27")
sk:send("GET / HTTP/1.1\r\nHost: 115.239.210.27\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
sk=net.createConnection(net.TCP, 1) sk:on("receive", function(sck, c) print(c) end )
sk:on("connection", function(sck) sck:send("GET / HTTPS/1.1\r\nHost: www.google.com.hk\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n") end ) sk:connect(443,"173.194.72.199")
wifi.sta.setip({ip="192.168.18.119",netmask="255.255.255.0",gateway="192.168.18.1"})
uart.on("data","\r",function(input) if input=="quit\r" then uart.on("data") else print(input) end end, 0)
uart.on("data","\n",function(input) if input=="quit\n" then uart.on("data") else print(input) end end, 0)
uart.on("data", 5 ,function(input) if input=="quit\r" then uart.on("data") else print(input) end end, 0)
uart.on("data", 0 ,function(input) if input=="q" then uart.on("data") else print(input) end end, 0)
uart.on("data","\r",function(input) if input=="quit" then uart.on("data") else print(input) end end, 1)
for k, v in pairs(file.list()) do print('file:'..k..' len:'..v) end
m=mqtt.Client()
m:connect("192.168.18.101",1883)
m:subscribe("/topic",0,function(m) print("sub done") end)
m:on("message",function(m,t,pl) print(t..":") if pl~=nil then print(pl) end end )
m:publish("/topic","hello",0,0)
uart.setup(0,9600,8,0,1,0)
sv=net.createServer(net.TCP, 60)
global_c = nil
sv:listen(9999, function(c)
if global_c~=nil then
global_c:close()
end
global_c=c
c:on("receive",function(sck,pl) uart.write(0,pl) end)
end)
uart.on("data",4, function(data)
if global_c~=nil then
global_c:send(data)
end
end, 0)
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")
-- 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
-- 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
cc = coap.Client()
cc:get(coap.CON, "coap://192.168.18.100:5683/.well-known/core")
cc:post(coap.NON, "coap://192.168.18.100:5683/", "Hello")
file.open("test1.txt", "a+") for i = 1, 100*1000 do file.write("x") end file.close() print("Done.")
for n,s in pairs(file.list()) do print(n.." size: "..s) end
file.remove("test1.txt")
for n,s in pairs(file.list()) do print(n.." size: "..s) end
file.open("test2.txt", "a+") for i = 1, 1*1000 do file.write("x") end file.close() print("Done.")
function TestDNSLeak()
c=net.createConnection(net.TCP, 0)
c:connect(80, "bad-name.tlddfdf")
tmr.alarm(1, 3000, 0, function() print("hack socket close, MEM: "..node.heap()) c:close() end) -- socket timeout hack
print("MEM: "..node.heap())
end
v="abc%0D%0Adef"
print(string.gsub(v, "%%(%x%x)", function(x) return string.char(tonumber(x, 16)) end))
function ex(x) string.find("abc%0Ddef","bc") return 's' end
string.gsub("abc%0Ddef", "%%(%x%x)", ex)
function ex(x) string.char(35) return 's' end
string.gsub("abc%0Ddef", "%%(%x%x)", ex) print("hello")
function ex(x) string.lower('Ab') return 's' end
string.gsub("abc%0Ddef", "%%(%x%x)", ex) print("hello")
v="abc%0D%0Adef"
pcall(function() print(string.gsub(v, "%%(%x%x)", function(x) return string.char(tonumber(x, 16)) end)) end)
mosca -v | bunyan
m=mqtt.Client()
m:connect("192.168.18.88",1883)
topic={}
topic["/topic1"]=0
topic["/topic2"]=0
m:subscribe(topic,function(m) print("sub done") end)
m:on("message",function(m,t,pl) print(t..":") if pl~=nil then print(pl) end end )
m:publish("/topic1","hello",0,0)
m:publish("/topic3","hello",0,0) m:publish("/topic4","hello",0,0)
m=mqtt.Client()
m:connect("192.168.18.88",1883)
m:subscribe("/topic1",0,function(m) print("sub done") end)
m:subscribe("/topic2",0,function(m) print("sub done") end)
m:on("message",function(m,t,pl) print(t..":") if pl~=nil then print(pl) end end )
m:publish("/topic1","hello",0,0)
m:publish("/topic3","hello",0,0) m:publish("/topic4","hello",0,0)
m:publish("/topic1","hello1",0,0) m:publish("/topic2","hello2",0,0)
m:publish("/topic1","hello",1,0)
m:subscribe("/topic3",0,function(m) print("sub done") end)
m:publish("/topic3","hello3",2,0)
m=mqtt.Client()
m:connect("192.168.18.88",1883, function(con) print("connected hello") end)
m=mqtt.Client()
m:on("connect",function(m) print("connection") end )
m:connect("192.168.18.88",1883)
m:on("offline",function(m) print("disconnection") end )
m=mqtt.Client()
m:on("connect",function(m) print("connection "..node.heap()) end )
m:on("offline", function(conn)
if conn == nil then print("conn is nil") end
print("Reconnect to broker...")
print(node.heap())
conn:connect("192.168.18.88",1883,0,1)
end)
m:connect("192.168.18.88",1883,0,1)
m=mqtt.Client()
m:on("connect",function(m) print("connection "..node.heap()) end )
m:on("offline", function(conn)
if conn == nil then print("conn is nil") end
print("Reconnect to broker...")
print(node.heap())
conn:connect("192.168.18.88",1883)
end)
m:connect("192.168.18.88",1883)
m:close()
m=mqtt.Client()
m:connect("192.168.18.88",1883)
m:on("message",function(m,t,pl) print(t..":") if pl~=nil then print(pl) end end )
m:subscribe("/topic1",0,function(m) print("sub done") end)
m:publish("/topic1","hello3",2,0) m:publish("/topic1","hello2",2,0)
m:publish("/topic1","hello3",0,0) m:publish("/topic1","hello2",2,0)
m:subscribe("/topic2",2,function(m) print("sub done") end)
m:publish("/topic2","hello3",0,0) m:publish("/topic2","hello2",2,0)
m=mqtt.Client()
m:on("connect",function(m)
print("connection "..node.heap())
m:subscribe("/topic1",0,function(m) print("sub done") end)
m:publish("/topic1","hello3",0,0) m:publish("/topic1","hello2",2,0)
end )
m:on("offline", function(conn)
print("disconnect to broker...")
print(node.heap())
end)
m:connect("192.168.18.88",1883,0,1)
-- serout( pin, firstLevel, delay_table, [repeatNum] )
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.mode(1,gpio.OUTPUT,gpio.PULLUP)
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
-- Lua: mqtt.Client(clientid, keepalive, user, pass)
-- test with cloudmqtt.com
m_dis={}
function dispatch(m,t,pl)
if pl~=nil and m_dis[t] then
m_dis[t](pl)
end
end
function topic1func(pl)
print("get1: "..pl)
end
function topic2func(pl)
print("get2: "..pl)
end
m_dis["/topic1"]=topic1func
m_dis["/topic2"]=topic2func
m=mqtt.Client("nodemcu1",60,"test","test123")
m:on("connect",function(m)
print("connection "..node.heap())
m:subscribe("/topic1",0,function(m) print("sub done") end)
m:subscribe("/topic2",0,function(m) print("sub done") end)
m:publish("/topic1","hello",0,0) m:publish("/topic2","world",0,0)
end )
m:on("offline", function(conn)
print("disconnect to broker...")
print(node.heap())
end)
m:on("message",dispatch )
m:connect("m11.cloudmqtt.com",11214,0,1)
-- Lua: mqtt:connect( host, port, secure, auto_reconnect, function(client) )
tmr.alarm(0,10000,1,function() local pl = "time: "..tmr.time()
m:publish("/topic1",pl,0,0)
end)
--init.lua, something like this
countdown = 3
tmr.alarm(0,1000,1,function()
print(countdown)
countdown = countdown-1
if countdown<1 then
tmr.stop(0)
countdown = nil
local s,err
if file.open("user.lc") then
file.close()
s,err = pcall(function() dofile("user.lc") end)
else
s,err = pcall(function() dofile("user.lua") end)
end
if not s then print(err) end
end
end)
print("hello NodeMCU")
# Ignore everything
*
# But not this file itself.
!.gitignore
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment