Commit 04ce0adf authored by Marcel Stör's avatar Marcel Stör Committed by GitHub
Browse files

Next 1.5.4.1 master drop (#1627)

* add u8g.fb_rle display

* move comm drivers to u8g_glue.c

* disable fb_rle per default

* implement file.size for spiffs (#1516)

Another bug squashed!

* Fix start-up race between UART & start_lua. (#1522)

Input during startup (especially while doing initial filesystem format)
ran the risk of filling up the task queue, preventing the start_lua task
from being queued, and hence NodeMCU would not start up that time.

* Reimplemented esp_init_data_default.

To work around the pesky "rf_cal[0] !=0x05" hang when booting on a chip
which doesn't have esp_init_data written to it.

It is no longer possible to do the writing of the esp_init_data_default
from within nodemcu_init(), as the SDK now hangs long before it gets
there.  As such, I've had to reimplement this in our user_start_trampoline
and get it all done before the SDK has a chance to look for the init data.
It's unfortunate that we have to spend IRAM on this, but I see no better
alternative at this point.

* Replace hardcoded init data with generated data from SDK

The esp_init_data_default.bin is now extracted from the SDK (and its
patch file, if present), and the contents are automatically embedded
into user_main.o.

* Rework flashing instructions

Clarifies issues around SDK init data and hopefully clears up some
confusion, when paired with the esp_init_data_default changes in
NodeMCU.

* Fix typo

* Fixes the gpio.serout problem from #1534 (#1535)

* Fix some issues in gpio.serout
* Minor cleanup

* fix dereferencing NULL pointer in vfs_errno() (#1539)

* add map ids for flash sizes 32m-c2, 64m, 128m in user_rf_cal_sector_set() (#1529)

* Somfy/TELIS driver (#1521)

* Reduced LUAL_BUFFERSIZE to 256. Should free up some stack (#1530)

* avoid task queue overrun for serial input (#1540)

Thank you.

* Increase irom0_0_seg size for PR build

* Improve reliability of FS detection. (#1528)

* Version to make filesystem detection more reliable
* Improve bad fs detection

* Version of printf that doesn't suffer from buffer overflows (#1564)

* Small improvement to http client (#1558)

* Remove luaL_buffer from file_g_read() (#1541)

* remove luaL_buffer from file_g_read()
- avoid memory leak when function gets terminated by lua_error
- skip scanning for end_char when reading until EOF
* attempt to free memory in any case

* Change HTTP failures from debug to error messages (#1568)

* Change HTTP failures from debug to error messages

* Add tag to HTTP error messages

* Create macro for error msg and improve dbg msg

* Add ssd1306_128x32 for U8G (#1571)

* Update CONTRIBUTING.md

* Add support to mix ws2812.buffer objects.  (#1575)

* Add load/dump/mix/power operations on the buffer object
* Calculate the pixel value in mix and then clip to the range.
* Fixed the two wrong userdata types
* Added a couple more useful methods
* Add support for shifting a piece of the buffer.
* Fix a minor bug with offset shifts

* Update to the wifi module (#1497)

* Removed inline documentation for several functions and update comments
Since documentation is now part of the repository, the inline
documentation just adds to the already huge wifi.c

* Wifi module: add new functionality, update documentation

Functions Added:
wifi.getdefaultmode(): returns default wifi opmode
wifi.sta.apchange(): select alternate cached AP
wifi.sta.apinfo(): get cached AP list 
wifi.sta.aplimit(): set cached AP limit
wifi.sta.getapindex(): get index of currently configured AP
wifi.sta.getdefaultconfig(): get default station configuration
wifi.ap.getdefaultconfig(): get default AP configuration

functions modified:
wifi.setmode: saving mode to flash is now optional
wifi.sta.config: now accepts table as an argument and save config to
flash is now optional
wifi.sta.getconfig: added option to return table
wifi.ap.config: save config to flash is now optional
wifi.ap.getconfig: added option to return table

Documentation changes:
- Modified documentation to reflect above changes
- Removed unnecessary inline documentation from `wifi.c` 
- Updated documentation for `wifi.sta.disconnect`to address issue #1480 
- Fixed inaccurate documentation for function `wifi.sleeptype`
- Added more details to `wifi.nullmodesleep()`

* Move function `wifi.sleeptype()` to `wifi.sta.sleeptype()`

* Fixed problem where wifi.x.getconfig() returned invalid strings when
ssid or password were set to maximum length.

* fix error in documentation for `wifi.sta.getapindex`

* Renamed some wifi functions
wifi.sta.apinfo -> getapinfo
wifi.sta.aplimit -> setaplimit 
wifi.sta.apchange -> changeap

also organized the wifi_station_map array

* Make the MQTT PING functionality work better. (#1557)

Deal with flow control stopped case

* Implement object model for files (#1532)

* Eus channelfix (#1583)

Squashed commits included:

Bug fixes and final implementation
- Added Content-Length: 0 to all headers
- Endpoint name checks not using trailing space so cache-busting techniques can be used (i.e., append a nonce to the URL)
- Track when connecting so APList scan doesn't take place during (which changes the channel)
- More debugging output added to assist in tracking down some issues

Added /status.json endpoint for phone apps/XHR to get JSON response

Station Status caching for wifi channel workaround + AJAX/CORS
- During checkstation poll, cache the last station status
- Shut down the station if status = 2,3,4 and channel is different than SoftAP
- Add Access-Control-Allow-Origin: * to endpoint responses used by a service
- Add a /setwifi GET endpoint for phone apps/XHR to use (same parameters as /update endpoint). Returns a JSON response containing chip id and status code.
- Add handler for OPTIONS verb (needed for CORS support)

Wi-Fi Channel Issue Workaround
- Do a site survey upon startup, set SoftAP channel to the strongest rssi's channel
- Compare successful station connect channel to SoftAP's. If different, then defer the Lua success callback to the end. Shut down Station and start the SoftAP back up with original channel.
- After the 10 second shutdown timer fires, check to see if success callback was already called. If not, then call it while starting the Station back up.

HTTP Response and DNS enhancements
- If DNS's UDP buffer fills up, keep going as non-fatal. It's UDP and not guaranteed anyways. I've seen this occur when connecting a PC to the SoftAP and every open program tries to phone home at the same time, overwhelming the EUS DNS server.
- Support for detecting/handling pre-gzipped `enduser_setup.html` (and `http_html_backup`) payload. Nice for keeping the size of the `state->http_payload_data` as small as possible (also makes minimization not as critical)
- Corrected misuse of HTTP 401 response status (changed one occurrence to 400/Bad Request, and changed another to 405/Method Not Allowed)

* Normalized formatting (tabs-to-spaces)
* Added documentation
* Corrected misuse of strlen for binary (gzip) data.
* Added NULL check after malloc

* fix vfs_lseek() result checking in enduser_setup and clarify SPIFFS_lseek() return value (#1570)

* Fix link

* Overhaul flashing docs once again (#1587)

* Add chapter about determine flash size plus small fixes
* Rewrite esptool.py chapter, move flash size chapter to end

* i2c - allow slave stretching SCL (just loop and check) (#1589)

* Add note on dev board usage of SPI bus 0 (#1591)

* Turn SPI busses note to admonition note

* support for custom websocket headers (#1573)

Looks good to me. Thank you.

Also:
 - allow for '\0's in received messages

* add client:config for setting websocket headers

Also:
 - headers are case-insensitive now

* fix docs

* fix typo

* remove unnecessary luaL_argcheck calls

* replace os_sprintf with simple string copy

* Handle error condition in file.read() (#1599)

* handle error condition in file.read()

* simplify loop initialization

* Fix macro as suggested in #1548

* Extract and hoist net receive callbacks

This is done to avoid the accidental upval binding

* Fix typo at rtctime.md

rtctime.dsleep -> rtctime.dsleep_aligned
parent 7b83bbb2
......@@ -20,19 +20,19 @@
// Set generic spiffs debug output call.
#ifndef SPIFFS_DBG
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
#define SPIFFS_DBG(...) //dbg_printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for garbage collecting.
#ifndef SPIFFS_GC_DBG
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
#define SPIFFS_GC_DBG(...) //dbg_printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for caching.
#ifndef SPIFFS_CACHE_DBG
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
#define SPIFFS_CACHE_DBG(...) //dbg_printf(__VA_ARGS__)
#endif
// Set spiffs debug output call for system consistency checks.
#ifndef SPIFFS_CHECK_DBG
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
#define SPIFFS_CHECK_DBG(...) //dbg_printf(__VA_ARGS__)
#endif
// Enable/disable API functions to determine exact number of bytes
......@@ -211,7 +211,7 @@
#endif
#if SPIFFS_TEST_VISUALISATION
#ifndef spiffs_printf
#define spiffs_printf(...) printf(__VA_ARGS__)
#define spiffs_printf(...) dbg_printf(__VA_ARGS__)
#endif
// spiffs_printf argument for a free page
#ifndef SPIFFS_TEST_VIS_FREE_STR
......
......@@ -292,27 +292,60 @@ s32_t spiffs_probe(
SPIFFS_CHECK_RES(res);
}
// check that we have sane number of blocks
if (bix_count[0] < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS;
// check that the order is correct, take aborted erases in calculation
// Note that bix_count[0] should be blockcnt, [1] should be blockcnt - 1
// and [2] should be blockcnt - 3
// first block aborted erase
if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 1) {
return (bix_count[1]+1) * cfg->log_block_size;
}
int fs_size;
if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 2) {
fs_size = bix_count[1]+1;
} else
// second block aborted erase
if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 2) {
return bix_count[0] * cfg->log_block_size;
}
if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 3) {
fs_size = bix_count[0];
} else
// third block aborted erase
if (magic[2] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[1] == 1) {
return bix_count[0] * cfg->log_block_size;
}
fs_size = bix_count[0];
} else
// no block has aborted erase
if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 1) {
return bix_count[0] * cfg->log_block_size;
if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 2) {
fs_size = bix_count[0];
} else {
return SPIFFS_ERR_PROBE_NOT_A_FS;
}
// check that we have sane number of blocks
if (fs_size < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS;
dummy_fs.block_count = fs_size;
// Now verify that there is at least one good block at the end
for (bix = fs_size - 1; bix >= 3; bix--) {
spiffs_obj_id end_magic;
paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, bix);
#if SPIFFS_HAL_CALLBACK_EXTRA
// not any proper fs to report here, so callback with null
// (cross fingers that no-one gets angry)
res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&end_magic);
#else
res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&end_magic);
#endif
if (res < 0) {
return SPIFFS_ERR_PROBE_NOT_A_FS;
}
if (end_magic == (spiffs_obj_id)(-1)) {
if (bix < fs_size - 1) {
return SPIFFS_ERR_PROBE_NOT_A_FS;
}
} else if (end_magic != SPIFFS_MAGIC(&dummy_fs, bix)) {
return SPIFFS_ERR_PROBE_NOT_A_FS;
} else {
break;
}
}
return SPIFFS_ERR_PROBE_NOT_A_FS;
return fs_size * cfg->log_block_size;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
......
......@@ -137,7 +137,7 @@
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#else // SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - ((bix) < 3 ? (1<<(bix)) - 1 : (bix)<<2))))
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC
......
......@@ -1178,9 +1178,6 @@ struct _u8g_t
u8g_state_cb state_cb;
u8g_box_t current_page; /* current box of the visible page */
uint8_t i2c_addr;
uint8_t use_delay;
};
#define u8g_GetFontAscent(u8g) ((u8g)->font_ref_ascent)
......
......@@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
DEFINES += -DESP_INIT_DATA_DEFAULT="\"$(SDK_DIR)/bin/esp_init_data_default.bin\""
#############################################################
# Recursion Magic - Don't touch this!!
......
......@@ -29,11 +29,21 @@
#include "rtc/rtctime.h"
#endif
#define SIG_LUA 0
#define SIG_UARTINPUT 1
#define TASK_QUEUE_LEN 4
static os_event_t *taskQueue;
static task_handle_t input_sig;
static uint8 input_sig_flag = 0;
/* Contents of esp_init_data_default.bin */
extern const uint32_t init_data[];
extern const uint32_t init_data_end[];
__asm__(
/* Place in .text for same reason as user_start_trampoline */
".section \".text\"\n"
".align 4\n"
"init_data:\n"
".incbin \"" ESP_INIT_DATA_DEFAULT "\"\n"
"init_data_end:\n"
".previous\n"
);
/* Note: the trampoline *must* be explicitly put into the .text segment, since
* by the time it is invoked the irom has not yet been mapped. This naturally
......@@ -50,6 +60,31 @@ void TEXT_SECTION_ATTR user_start_trampoline (void)
rtctime_early_startup ();
#endif
/* Re-implementation of default init data deployment. The SDK does not
* appear to be laying down its own version of init data anymore, so
* we have to do it again. To see whether we need to, we read out
* the flash size and do a test for esp_init_data based on that size.
* If it's missing, we need to initialize it *right now* before the SDK
* starts up and gets stuck at "rf_cal[0] !=0x05,is 0xFF".
* If the size byte is wrong, then we'll end up fixing up the init data
* again on the next boot, after we've corrected the size byte.
* Only remaining issue is lack of spare code bytes in iram, so this
* is deliberately quite terse and not as readable as one might like.
*/
SPIFlashInfo sfi;
SPIRead (0, (uint32_t *)(&sfi), sizeof (sfi)); // Cache read not enabled yet, safe to use
if (sfi.size < 2) // Compensate for out-of-order 4mbit vs 2mbit values
sfi.size ^= 1;
uint32_t flash_end_addr = (256 * 1024) << sfi.size;
uint32_t init_data_hdr = 0xffffffff;
uint32_t init_data_addr = flash_end_addr - 4 * SPI_FLASH_SEC_SIZE;
SPIRead (init_data_addr, &init_data_hdr, sizeof (init_data_hdr));
if (init_data_hdr == 0xffffffff)
{
SPIEraseSector (init_data_addr);
SPIWrite (init_data_addr, init_data, 4 * (init_data_end - init_data));
}
call_user_start ();
}
......@@ -58,17 +93,18 @@ static void start_lua(task_param_t param, uint8 priority) {
char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
NODE_DBG("Task task_lua started.\n");
lua_main( 2, lua_argv );
// Only enable UART interrupts once we've successfully started up,
// otherwise the task queue might fill up with input events and prevent
// the start_lua task from being posted.
ETS_UART_INTR_ENABLE();
}
static void handle_input(task_param_t flag, uint8 priority) {
// c_printf("HANDLE_INPUT: %u %u\n", flag, priority); REMOVE
lua_handle_input (flag);
}
static task_handle_t input_sig;
task_handle_t user_get_input_sig(void) {
return input_sig;
(void)priority;
if (flag & 0x8000) {
input_sig_flag = flag & 0x4000 ? 1 : 0;
}
lua_handle_input (flag & 0x01);
}
bool user_process_input(bool force) {
......@@ -92,9 +128,7 @@ void nodemcu_init(void)
// Fit hardware real flash size.
flash_rom_set_size_byte(flash_safe_get_size_byte());
// Reboot to get SDK to use (or write) init data at new location
system_restart ();
// Don't post the start_lua task, we're about to reboot...
return;
}
......@@ -107,7 +141,7 @@ void nodemcu_init(void)
#ifdef BUILD_SPIFFS
if (!vfs_mount("/FLASH", 0)) {
// Failed to mount -- try reformat
c_printf("Formatting file system. Please wait...\n");
dbg_printf("Formatting file system. Please wait...\n");
if (!vfs_format()) {
NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
......@@ -118,7 +152,8 @@ void nodemcu_init(void)
#endif
// endpoint_setup();
task_post_low(task_get_id(start_lua),'s');
if (!task_post_low(task_get_id(start_lua),'s'))
NODE_ERR("Failed to post the start_lua task!\n");
}
#ifdef LUA_USE_MODULES_WIFI
......@@ -146,7 +181,7 @@ void user_rf_pre_init(void)
uint32
user_rf_cal_sector_set(void)
{
enum flash_size_map size_map = system_get_flash_size_map();
enum ext_flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
......@@ -165,9 +200,18 @@ user_rf_cal_sector_set(void)
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
case FLASH_SIZE_32M_MAP_2048_2048:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
......@@ -191,7 +235,7 @@ void user_init(void)
UartBautRate br = BIT_RATE_DEFAULT;
input_sig = task_get_id(handle_input);
uart_init (br, br, input_sig);
uart_init (br, br, input_sig, &input_sig_flag);
#ifndef NODE_DEBUG
system_set_os_print(0);
......
......@@ -47,18 +47,10 @@
#define PORT_INSECURE 80
#define PORT_MAX_VALUE 65535
// TODO: user agent configurable
#define WS_INIT_HEADERS "GET %s HTTP/1.1\r\n"\
"Host: %s:%d\r\n"\
"Upgrade: websocket\r\n"\
"Connection: Upgrade\r\n"\
"User-Agent: ESP8266\r\n"\
"Sec-Websocket-Key: %s\r\n"\
"Sec-WebSocket-Protocol: chat\r\n"\
"Sec-WebSocket-Version: 13\r\n"\
"\r\n"
#define WS_INIT_HEADERS_LENGTH 169
#define WS_INIT_REQUEST "GET %s HTTP/1.1\r\n"\
"Host: %s:%d\r\n"
#define WS_INIT_REQUEST_LENGTH 30
#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define WS_GUID_LENGTH 36
......@@ -77,6 +69,13 @@
#define WS_OPCODE_PING 0x9
#define WS_OPCODE_PONG 0xA
header_t DEFAULT_HEADERS[] = {
{"User-Agent", "ESP8266"},
{"Sec-WebSocket-Protocol", "chat"},
{0}
};
header_t *EMPTY_HEADERS = DEFAULT_HEADERS + sizeof(DEFAULT_HEADERS) / sizeof(header_t) - 1;
static char *cryptoSha1(char *data, unsigned int len) {
SHA1_CTX ctx;
SHA1Init(&ctx);
......@@ -128,6 +127,44 @@ static void generateSecKeys(char **key, char **expectedKey) {
os_free(keyEncrypted);
}
static char *_strcpy(char *dst, char *src) {
while(*dst++ = *src++);
return dst - 1;
}
static int headers_length(header_t *headers) {
int length = 0;
for(; headers->key; headers++)
length += strlen(headers->key) + strlen(headers->value) + 4;
return length;
}
static char *sprintf_headers(char *buf, ...) {
char *dst = buf;
va_list args;
va_start(args, buf);
for(header_t *header_set = va_arg(args, header_t *); header_set; header_set = va_arg(args, header_t *))
for(header_t *header = header_set; header->key; header++) {
va_list args2;
va_start(args2, buf);
for(header_t *header_set2 = va_arg(args2, header_t *); header_set2; header_set2 = va_arg(args2, header_t *))
for(header_t *header2 = header_set2; header2->key; header2++) {
if(header == header2)
goto ok;
if(!strcasecmp(header->key, header2->key))
goto skip;
}
ok:
dst = _strcpy(dst, header->key);
dst = _strcpy(dst, ": ");
dst = _strcpy(dst, header->value);
dst = _strcpy(dst, "\r\n");
skip:;
}
dst = _strcpy(dst, "\r\n");
return dst;
}
static void ws_closeSentCallback(void *arg) {
NODE_DBG("ws_closeSentCallback \n");
struct espconn *conn = (struct espconn *) arg;
......@@ -452,7 +489,7 @@ static void ws_receiveCallback(void *arg, char *buf, unsigned short len) {
} else if (opCode == WS_OPCODE_PONG) {
// ping alarm was already reset...
} else {
if (ws->onReceive) ws->onReceive(ws, payload, opCode);
if (ws->onReceive) ws->onReceive(ws, payloadLength, payload, opCode);
}
os_free(payload);
}
......@@ -509,7 +546,7 @@ static void ws_initReceiveCallback(void *arg, char *buf, unsigned short len) {
}
// Check server has valid sec key
if (strstr(buf, WS_HTTP_SEC_WEBSOCKET_ACCEPT) == NULL || strstr(buf, ws->expectedSecKey) == NULL) {
if (strstr(buf, ws->expectedSecKey) == NULL) {
NODE_DBG("Server has invalid response\n");
ws->knownFailureCode = -7;
if (ws->isSecure)
......@@ -550,12 +587,31 @@ static void connect_callback(void *arg) {
char *key;
generateSecKeys(&key, &ws->expectedSecKey);
char buf[WS_INIT_HEADERS_LENGTH + strlen(ws->path) + strlen(ws->hostname) + strlen(key)];
int len = os_sprintf(buf, WS_INIT_HEADERS, ws->path, ws->hostname, ws->port, key);
header_t headers[] = {
{"Upgrade", "websocket"},
{"Connection", "Upgrade"},
{"Sec-WebSocket-Key", key},
{"Sec-WebSocket-Version", "13"},
{0}
};
os_free(key);
header_t *extraHeaders = ws->extraHeaders ? ws->extraHeaders : EMPTY_HEADERS;
char buf[WS_INIT_REQUEST_LENGTH + strlen(ws->path) + strlen(ws->hostname) +
headers_length(DEFAULT_HEADERS) + headers_length(headers) + headers_length(extraHeaders) + 2];
NODE_DBG("connecting\n");
int len = os_sprintf(
buf,
WS_INIT_REQUEST,
ws->path,
ws->hostname,
ws->port
);
len = sprintf_headers(buf + len, headers, extraHeaders, DEFAULT_HEADERS, 0) - buf;
os_free(key);
NODE_DBG("request: %s", buf);
if (ws->isSecure)
espconn_secure_send(conn, (uint8_t *) buf, len);
else
......@@ -630,7 +686,7 @@ static void dns_callback(const char *hostname, ip_addr_t *addr, void *arg) {
ws_info *ws = (ws_info *) conn->reverse;
if (ws->conn == NULL || ws->connectionState == 4) {
return;
return;
}
if (addr == NULL) {
......
......@@ -40,9 +40,14 @@
struct ws_info;
typedef void (*ws_onConnectionCallback)(struct ws_info *wsInfo);
typedef void (*ws_onReceiveCallback)(struct ws_info *wsInfo, char *message, int opCode);
typedef void (*ws_onReceiveCallback)(struct ws_info *wsInfo, int len, char *message, int opCode);
typedef void (*ws_onFailureCallback)(struct ws_info *wsInfo, int errorCode);
typedef struct {
char *key;
char *value;
} header_t;
typedef struct ws_info {
int connectionState;
......@@ -51,6 +56,7 @@ typedef struct ws_info {
int port;
char *path;
char *expectedSecKey;
header_t *extraHeaders;
struct espconn *conn;
void *reservedData;
......
This diff is collapsed.
......@@ -44,7 +44,7 @@ print(gpio.read(pin))
```
## Getting Started
1. [Build the firmeware](build.md) with the modules you need.
1. [Build the firmware](build.md) with the modules you need.
1. [Flash the firmware](flash.md) to the chip.
1. [Upload code](upload.md) to the firmware.
......
......@@ -7,10 +7,29 @@ This module provides a simple way of configuring ESP8266 chips without using a s
![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.
After running [`enduser_setup.start()`](#enduser_setupstart), a wireless network named "SetupGadget_XXXXXX" will start. Connect to that SSID and then navigate to the root
of any website (e.g., `http://example.com/` will work, but do not use `.local` domains because it will fail on iOS). A web page similar to the picture above will load, allowing the
end user to provide their Wi-Fi information.
After an IP address has been successfully obtained, then this module will stop as if [`enduser_setup.stop()`](#enduser_setupstop) had been called. There is a 10-second delay before
teardown to allow connected clients to obtain a last status message while the SoftAP is still active.
Alternative HTML can be served by placing a file called `enduser_setup.html` on the filesystem. Everything needed by the web page must be included in this one file. This file will be kept
in RAM, so keep it as small as possible. The file can be gzip'd ahead of time to reduce the size (i.e., using `gzip -n` or `zopfli`), and when served, the End User Setup module will add
the appropriate `Content-Encoding` header to the response. *Note: Even if gzipped, the file still needs to be named `enduser_setup.html`.*
The following HTTP endpoints exist:
|Endpoint|Description|
|--------|-----------|
|/|Returns HTML for the web page. Will return the contents of `enduser_setup.html` if it exists on the filesystem, otherwise will return a page embedded into the firmware image.|
|/aplist|Forces the ESP8266 to perform a site survey across all channels, reporting access points that it can find. Return payload is a JSON array: `[{"ssid":"foobar","rssi":-36,"chan":3}]`|
|/generate_204|Returns a HTTP 204 status (expected by certain Android clients during Wi-Fi connectivity checks)|
|/status|Returns plaintext status description, used by the web page|
|/status.json|Returns a JSON payload containing the ESP8266's chip id in hexadecimal format and the status code: 0=Idle, 1=Connecting, 2=Wrong Password, 3=Network not Found, 4=Failed, 5=Success|
|/setwifi|Endpoint intended for services to use for setting the wifi credentials. Identical to `/update` except returns the same payload as `/status.json` instead of redirecting to `/`.|
|/update|Form submission target. Example: `http://example.com/update?wifi_ssid=foobar&wifi_password=CorrectHorseBatteryStaple`. Must be a GET request. Will redirect to `/` when complete. |
Alternative HTML can be served by placing a file called `enduser_setup.html` in the filesystem. This file will be kept in RAM, so keep it as small as possible.
## enduser_setup.manual()
......@@ -53,7 +72,7 @@ Starts the captive portal.
#### Parameters
- `onConnected()` 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.
- `onDebug()` callback is disabled by default (controlled by `#define ENDUSER_SETUP_DEBUG_ENABLE` in `enduser_setup.c`). It is intended to be used to find internal issues in the module. `string` contains a description of what is going on.
#### Returns
`nil`
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -84,7 +84,7 @@ Reads multi bytes.
#### Parameters
- `pin` 1~12, I/O index
- `size` number of bytes to be read from slave device
- `size` number of bytes to be read from slave device (up to 256)
#### Returns
`string` bytes read from slave device
......
......@@ -55,7 +55,7 @@ rtctime.dsleep(5000000, 4)
For applications where it is necessary to take samples with high regularity, this function is useful. It provides an easy way to implement a "wake up on the next 5-minute boundary" scheme, without having to explicitly take into account how long the module has been active for etc before going back to sleep.
#### Syntax
`rtctime.dsleep(aligned_us, minsleep_us [, option])`
`rtctime.dsleep_aligned(aligned_us, minsleep_us [, option])`
#### Parameters
- `aligned_us` boundary interval in microseconds
......
......@@ -12,7 +12,7 @@ When compiled together with the [rtctime](rtctime.md) module it also offers seam
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).
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])`
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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