Commit 7b83bbb2 authored by Arnim Läuger's avatar Arnim Läuger Committed by GitHub
Browse files

Merge pull request #1519 from nodemcu/dev

Next 1.5.4.1 master drop
parents 8e48483c d96d7f23
...@@ -24,7 +24,6 @@ coap_queue_t *gQueue = NULL; ...@@ -24,7 +24,6 @@ coap_queue_t *gQueue = NULL;
typedef struct lcoap_userdata typedef struct lcoap_userdata
{ {
lua_State *L;
struct espconn *pesp_conn; struct espconn *pesp_conn;
int self_ref; int self_ref;
}lcoap_userdata; }lcoap_userdata;
...@@ -103,7 +102,6 @@ static int coap_create( lua_State* L, const char* mt ) ...@@ -103,7 +102,6 @@ static int coap_create( lua_State* L, const char* mt )
pesp_conn->state = ESPCONN_NONE; pesp_conn->state = ESPCONN_NONE;
NODE_DBG("UDP server/client is set.\n"); NODE_DBG("UDP server/client is set.\n");
cud->L = L;
pesp_conn->reverse = cud; pesp_conn->reverse = cud;
NODE_DBG("coap_create is called.\n"); NODE_DBG("coap_create is called.\n");
...@@ -129,7 +127,6 @@ static int coap_delete( lua_State* L, const char* mt ) ...@@ -129,7 +127,6 @@ static int coap_delete( lua_State* L, const char* mt )
cud->self_ref = LUA_NOREF; cud->self_ref = LUA_NOREF;
} }
cud->L = NULL;
if(cud->pesp_conn) if(cud->pesp_conn)
{ {
if(cud->pesp_conn->proto.udp->remote_port || cud->pesp_conn->proto.udp->local_port) if(cud->pesp_conn->proto.udp->remote_port || cud->pesp_conn->proto.udp->local_port)
...@@ -462,10 +459,8 @@ static int coap_regist( lua_State* L, const char* mt, int isvar ) ...@@ -462,10 +459,8 @@ static int coap_regist( lua_State* L, const char* mt, int isvar )
return luaL_error(L, "not enough memory"); return luaL_error(L, "not enough memory");
h->next = NULL; h->next = NULL;
h->name = NULL; h->name = NULL;
h->L = NULL;
} }
h->L = L;
h->name = name; h->name = name;
h->content_type = content_type; h->content_type = content_type;
......
...@@ -6,14 +6,21 @@ ...@@ -6,14 +6,21 @@
#include "platform.h" #include "platform.h"
#include "c_types.h" #include "c_types.h"
#include "c_stdlib.h" #include "c_stdlib.h"
#include "flash_fs.h" #include "vfs.h"
#include "../crypto/digests.h" #include "../crypto/digests.h"
#include "../crypto/mech.h" #include "../crypto/mech.h"
#include "lmem.h"
#include "user_interface.h" #include "user_interface.h"
#include "rom.h" #include "rom.h"
typedef struct {
const digest_mech_info_t *mech_info;
void *ctx;
uint8_t *k_opad;
} digest_user_datum_t;
/** /**
* hash = crypto.sha1(input) * hash = crypto.sha1(input)
* *
...@@ -150,11 +157,6 @@ static int crypto_lhash (lua_State *L) ...@@ -150,11 +157,6 @@ static int crypto_lhash (lua_State *L)
return 1; return 1;
} }
typedef struct digest_user_datum_t {
const digest_mech_info_t *mech_info;
void *ctx;
} digest_user_datum_t;
/* General Usage for extensible hash functions: /* General Usage for extensible hash functions:
* sha = crypto.new_hash("MD5") * sha = crypto.new_hash("MD5")
* sha.update("Data") * sha.update("Data")
...@@ -162,19 +164,30 @@ typedef struct digest_user_datum_t { ...@@ -162,19 +164,30 @@ typedef struct digest_user_datum_t {
* strdigest = crypto.toHex(sha.finalize()) * strdigest = crypto.toHex(sha.finalize())
*/ */
/* crypto.new_hash("MECHTYPE") */ #define WANT_HASH 0
static int crypto_new_hash (lua_State *L) #define WANT_HMAC 1
static int crypto_new_hash_hmac (lua_State *L, int what)
{ {
const digest_mech_info_t *mi = crypto_digest_mech (luaL_checkstring (L, 1)); const digest_mech_info_t *mi = crypto_digest_mech (luaL_checkstring (L, 1));
if (!mi) if (!mi)
return bad_mech (L); return bad_mech (L);
void *ctx = os_malloc (mi->ctx_size); size_t len = 0;
if (ctx==NULL) const char *key = 0;
return bad_mem (L); uint8_t *k_opad = 0;
if (what == WANT_HMAC)
{
key = luaL_checklstring (L, 2, &len);
k_opad = luaM_malloc (L, mi->block_size);
}
void *ctx = luaM_malloc (L, mi->ctx_size);
mi->create (ctx); mi->create (ctx);
if (what == WANT_HMAC)
crypto_hmac_begin (ctx, mi, key, len, k_opad);
// create a userdataum with specific metatable // create a userdataum with specific metatable
digest_user_datum_t *dudat = (digest_user_datum_t *)lua_newuserdata(L, sizeof(digest_user_datum_t)); digest_user_datum_t *dudat = (digest_user_datum_t *)lua_newuserdata(L, sizeof(digest_user_datum_t));
luaL_getmetatable(L, "crypto.hash"); luaL_getmetatable(L, "crypto.hash");
...@@ -183,10 +196,24 @@ static int crypto_new_hash (lua_State *L) ...@@ -183,10 +196,24 @@ static int crypto_new_hash (lua_State *L)
// Set pointers to the mechanics and CTX // Set pointers to the mechanics and CTX
dudat->mech_info = mi; dudat->mech_info = mi;
dudat->ctx = ctx; dudat->ctx = ctx;
dudat->k_opad = k_opad;
return 1; // Pass userdata object back return 1; // Pass userdata object back
} }
/* crypto.new_hash("MECHTYPE") */
static int crypto_new_hash (lua_State *L)
{
return crypto_new_hash_hmac (L, WANT_HASH);
}
/* crypto.new_hmac("MECHTYPE", "KEY") */
static int crypto_new_hmac (lua_State *L)
{
return crypto_new_hash_hmac (L, WANT_HMAC);
}
/* Called as object, params: /* Called as object, params:
1 - userdata "this" 1 - userdata "this"
2 - new string to add to the hash state */ 2 - new string to add to the hash state */
...@@ -197,7 +224,6 @@ static int crypto_hash_update (lua_State *L) ...@@ -197,7 +224,6 @@ static int crypto_hash_update (lua_State *L)
size_t sl; size_t sl;
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash"); dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
const digest_mech_info_t *mi = dudat->mech_info; const digest_mech_info_t *mi = dudat->mech_info;
...@@ -217,12 +243,14 @@ static int crypto_hash_finalize (lua_State *L) ...@@ -217,12 +243,14 @@ static int crypto_hash_finalize (lua_State *L)
size_t sl; size_t sl;
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash"); dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
const digest_mech_info_t *mi = dudat->mech_info; const digest_mech_info_t *mi = dudat->mech_info;
uint8_t digest[mi->digest_size]; // Allocate as local uint8_t digest[mi->digest_size]; // Allocate as local
mi->finalize (digest, dudat->ctx); if (dudat->k_opad)
crypto_hmac_finalize (dudat->ctx, mi, dudat->k_opad, digest);
else
mi->finalize (digest, dudat->ctx);
lua_pushlstring (L, digest, sizeof (digest)); lua_pushlstring (L, digest, sizeof (digest));
return 1; return 1;
...@@ -235,14 +263,21 @@ static int crypto_hash_gcdelete (lua_State *L) ...@@ -235,14 +263,21 @@ static int crypto_hash_gcdelete (lua_State *L)
digest_user_datum_t *dudat; digest_user_datum_t *dudat;
dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash"); dudat = (digest_user_datum_t *)luaL_checkudata(L, 1, "crypto.hash");
luaL_argcheck(L, dudat, 1, "crypto.hash expected");
os_free(dudat->ctx); // luaM_free() uses type info to obtain original size, so have to delve
// one level deeper and explicitly pass the size due to void*
luaM_realloc_ (L, dudat->ctx, dudat->mech_info->ctx_size, 0);
luaM_free (L, dudat->k_opad);
return 0; return 0;
} }
static sint32_t vfs_read_wrap (int fd, void *ptr, size_t len)
{
return vfs_read (fd, ptr, len);
}
/* rawdigest = crypto.hash("MD5", filename) /* rawdigest = crypto.hash("MD5", filename)
* strdigest = crypto.toHex(rawdigest) * strdigest = crypto.toHex(rawdigest)
*/ */
...@@ -254,17 +289,17 @@ static int crypto_flhash (lua_State *L) ...@@ -254,17 +289,17 @@ static int crypto_flhash (lua_State *L)
const char *filename = luaL_checkstring (L, 2); const char *filename = luaL_checkstring (L, 2);
// Open the file // Open the file
int file_fd = fs_open (filename, FS_RDONLY); int file_fd = vfs_open (filename, "r");
if(file_fd < FS_OPEN_OK) { if(!file_fd) {
return bad_file(L); return bad_file(L);
} }
// Compute hash // Compute hash
uint8_t digest[mi->digest_size]; uint8_t digest[mi->digest_size];
int returncode = crypto_fhash (mi, &fs_read, file_fd, digest); int returncode = crypto_fhash (mi, &vfs_read_wrap, file_fd, digest);
// Finish up // Finish up
fs_close(file_fd); vfs_close(file_fd);
if (returncode == ENOMEM) if (returncode == ENOMEM)
return bad_mem (L); return bad_mem (L);
...@@ -381,6 +416,7 @@ static const LUA_REG_TYPE crypto_map[] = { ...@@ -381,6 +416,7 @@ static const LUA_REG_TYPE crypto_map[] = {
{ LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) }, { LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) },
{ LSTRKEY( "new_hash" ), LFUNCVAL( crypto_new_hash ) }, { LSTRKEY( "new_hash" ), LFUNCVAL( crypto_new_hash ) },
{ LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) }, { LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) },
{ LSTRKEY( "new_hmac" ), LFUNCVAL( crypto_new_hmac ) },
{ LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) }, { LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) },
{ LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) }, { LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) },
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include "espconn.h" #include "espconn.h"
#include "lwip/tcp.h" #include "lwip/tcp.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "flash_fs.h" #include "vfs.h"
#include "task/task.h" #include "task/task.h"
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y))
...@@ -485,20 +485,20 @@ static int enduser_setup_http_load_payload(void) ...@@ -485,20 +485,20 @@ static int enduser_setup_http_load_payload(void)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload"); ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload");
int err = (FS_OPEN_OK -1); int err = VFS_RES_ERR;
int err2 = (FS_OPEN_OK -1); int err2 = VFS_RES_ERR;
int file_len = 0; int file_len = 0;
int f = fs_open(http_html_filename, fs_mode2flag("r")); int f = vfs_open(http_html_filename, "r");
if (f >= FS_OPEN_OK) { if (f) {
err = fs_seek(f, 0, FS_SEEK_END); err = vfs_lseek(f, 0, VFS_SEEK_END);
file_len = (int) fs_tell(f); file_len = (int) vfs_tell(f);
err2 = fs_seek(f, 0, FS_SEEK_SET); err2 = vfs_lseek(f, 0, VFS_SEEK_SET);
} }
const char cl_hdr[] = "Content-length:%5d\r\n\r\n"; const char cl_hdr[] = "Content-length:%5d\r\n\r\n";
const size_t cl_len = LITLEN(cl_hdr) + 3; /* room to expand %4d */ const size_t cl_len = LITLEN(cl_hdr) + 3; /* room to expand %4d */
if (f < FS_OPEN_OK || err < FS_OPEN_OK || err2 < FS_OPEN_OK) if (!f || err != VFS_RES_OK || err2 != VFS_RES_OK)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload unable to load file enduser_setup.html, loading backup HTML."); ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload unable to load file enduser_setup.html, loading backup HTML.");
...@@ -531,8 +531,8 @@ static int enduser_setup_http_load_payload(void) ...@@ -531,8 +531,8 @@ static int enduser_setup_http_load_payload(void)
c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200)); c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200));
offset += LITLEN(http_header_200); offset += LITLEN(http_header_200);
offset += c_sprintf(state->http_payload_data + offset, cl_hdr, file_len); offset += c_sprintf(state->http_payload_data + offset, cl_hdr, file_len);
fs_read(f, &(state->http_payload_data[offset]), file_len); vfs_read(f, &(state->http_payload_data[offset]), file_len);
fs_close(f); vfs_close(f);
return 0; return 0;
} }
......
...@@ -5,42 +5,95 @@ ...@@ -5,42 +5,95 @@
#include "platform.h" #include "platform.h"
#include "c_types.h" #include "c_types.h"
#include "flash_fs.h" #include "vfs.h"
#include "c_string.h" #include "c_string.h"
static volatile int file_fd = FS_OPEN_OK - 1; static int file_fd = 0;
static int rtc_cb_ref = LUA_NOREF;
// Lua: open(filename, mode)
static int file_open( lua_State* L ) static void table2tm( lua_State *L, vfs_time *tm )
{ {
size_t len; int idx = lua_gettop( L );
if((FS_OPEN_OK - 1)!=file_fd){
fs_close(file_fd); // extract items from table
file_fd = FS_OPEN_OK - 1; lua_getfield( L, idx, "year" );
} lua_getfield( L, idx, "mon" );
lua_getfield( L, idx, "day" );
lua_getfield( L, idx, "hour" );
lua_getfield( L, idx, "min" );
lua_getfield( L, idx, "sec" );
tm->year = luaL_optint( L, ++idx, 2016 );
tm->mon = luaL_optint( L, ++idx, 6 );
tm->day = luaL_optint( L, ++idx, 21 );
tm->hour = luaL_optint( L, ++idx, 0 );
tm->min = luaL_optint( L, ++idx, 0 );
tm->sec = luaL_optint( L, ++idx, 0 );
// remove items from stack
lua_pop( L, 6 );
}
const char *fname = luaL_checklstring( L, 1, &len ); static sint32_t file_rtc_cb( vfs_time *tm )
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); {
sint32_t res = VFS_RES_ERR;
const char *mode = luaL_optstring(L, 2, "r"); if (rtc_cb_ref != LUA_NOREF) {
lua_State *L = lua_getstate();
file_fd = fs_open(fname, fs_mode2flag(mode)); lua_rawgeti( L, LUA_REGISTRYINDEX, rtc_cb_ref );
lua_call( L, 0, 1 );
if(file_fd < FS_OPEN_OK){ if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) {
file_fd = FS_OPEN_OK - 1; table2tm( L, tm );
lua_pushnil(L); res = VFS_RES_OK;
} else { }
lua_pushboolean(L, 1);
// pop item returned by callback
lua_pop( L, 1 );
} }
return 1;
return res;
}
// Lua: on()
static int file_on(lua_State *L)
{
enum events{
ON_RTC = 0
};
const char *const eventnames[] = {"rtc", NULL};
int event = luaL_checkoption(L, 1, "rtc", eventnames);
switch (event) {
case ON_RTC:
luaL_unref(L, LUA_REGISTRYINDEX, rtc_cb_ref);
if ((lua_type(L, 2) == LUA_TFUNCTION) ||
(lua_type(L, 2) == LUA_TLIGHTFUNCTION)) {
lua_pushvalue(L, 2); // copy argument (func) to the top of stack
rtc_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
vfs_register_rtc_cb(file_rtc_cb);
} else {
rtc_cb_ref = LUA_NOREF;
vfs_register_rtc_cb(NULL);
}
break;
default:
break;
}
return 0;
} }
// Lua: close() // Lua: close()
static int file_close( lua_State* L ) static int file_close( lua_State* L )
{ {
if((FS_OPEN_OK - 1)!=file_fd){ if(file_fd){
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
} }
return 0; return 0;
} }
...@@ -50,7 +103,7 @@ static int file_format( lua_State* L ) ...@@ -50,7 +103,7 @@ static int file_format( lua_State* L )
{ {
size_t len; size_t len;
file_close(L); file_close(L);
if( !fs_format() ) if( !vfs_format() )
{ {
NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" ); NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" ); NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
...@@ -59,44 +112,77 @@ static int file_format( lua_State* L ) ...@@ -59,44 +112,77 @@ static int file_format( lua_State* L )
else{ else{
NODE_ERR( "format done.\n" ); NODE_ERR( "format done.\n" );
} }
return 0; return 0;
} }
#if defined(BUILD_SPIFFS) static int file_fscfg (lua_State *L)
{
uint32_t phys_addr, phys_size;
vfs_fscfg("/FLASH", &phys_addr, &phys_size);
extern spiffs fs; lua_pushinteger (L, phys_addr);
lua_pushinteger (L, phys_size);
return 2;
}
// Lua: open(filename, mode)
static int file_open( lua_State* L )
{
size_t len;
if(file_fd){
vfs_close(file_fd);
file_fd = 0;
}
const char *fname = luaL_checklstring( L, 1, &len );
const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
const char *mode = luaL_optstring(L, 2, "r");
file_fd = vfs_open(fname, mode);
if(!file_fd){
lua_pushnil(L);
} else {
lua_pushboolean(L, 1);
}
return 1;
}
// Lua: list() // Lua: list()
static int file_list( lua_State* L ) static int file_list( lua_State* L )
{ {
spiffs_DIR d; vfs_dir *dir;
struct spiffs_dirent e; vfs_item *item;
struct spiffs_dirent *pe = &e;
if (dir = vfs_opendir("")) {
lua_newtable( L ); lua_newtable( L );
SPIFFS_opendir(&fs, "/", &d); while (item = vfs_readdir(dir)) {
while ((pe = SPIFFS_readdir(&d, pe))) { lua_pushinteger(L, vfs_item_size(item));
// NODE_ERR(" %s size:%i\n", pe->name, pe->size); lua_setfield(L, -2, vfs_item_name(item));
lua_pushinteger(L, pe->size); vfs_closeitem(item);
lua_setfield( L, -2, pe->name ); }
vfs_closedir(dir);
return 1;
} }
SPIFFS_closedir(&d); return 0;
return 1;
} }
static int file_seek (lua_State *L) static int file_seek (lua_State *L)
{ {
static const int mode[] = {FS_SEEK_SET, FS_SEEK_CUR, FS_SEEK_END}; static const int mode[] = {VFS_SEEK_SET, VFS_SEEK_CUR, VFS_SEEK_END};
static const char *const modenames[] = {"set", "cur", "end", NULL}; static const char *const modenames[] = {"set", "cur", "end", NULL};
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
int op = luaL_checkoption(L, 1, "cur", modenames); int op = luaL_checkoption(L, 1, "cur", modenames);
long offset = luaL_optlong(L, 2, 0); long offset = luaL_optlong(L, 2, 0);
op = fs_seek(file_fd, offset, mode[op]); op = vfs_lseek(file_fd, offset, mode[op]);
if (op < 0) if (op < 0)
lua_pushnil(L); /* error */ lua_pushnil(L); /* error */
else else
lua_pushinteger(L, fs_tell(file_fd)); lua_pushinteger(L, vfs_tell(file_fd));
return 1; return 1;
} }
...@@ -105,12 +191,14 @@ static int file_exists( lua_State* L ) ...@@ -105,12 +191,14 @@ static int file_exists( lua_State* L )
{ {
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
spiffs_stat stat; vfs_item *stat = vfs_stat((char *)fname);
int rc = SPIFFS_stat(&fs, (char *)fname, &stat);
lua_pushboolean(L, (rc == SPIFFS_OK ? 1 : 0)); lua_pushboolean(L, stat ? 1 : 0);
if (stat) vfs_closeitem(stat);
return 1; return 1;
} }
...@@ -120,49 +208,43 @@ static int file_remove( lua_State* L ) ...@@ -120,49 +208,43 @@ static int file_remove( lua_State* L )
{ {
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid"); const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
file_close(L); file_close(L);
SPIFFS_remove(&fs, (char *)fname); vfs_remove((char *)fname);
return 0; return 0;
} }
// Lua: flush() // Lua: flush()
static int file_flush( lua_State* L ) static int file_flush( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
if(fs_flush(file_fd) == 0) if(vfs_flush(file_fd) == 0)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
} }
#if 0
// Lua: check()
static int file_check( lua_State* L )
{
file_close(L);
lua_pushinteger(L, fs_check());
return 1;
}
#endif
// Lua: rename("oldname", "newname") // Lua: rename("oldname", "newname")
static int file_rename( lua_State* L ) static int file_rename( lua_State* L )
{ {
size_t len; size_t len;
if((FS_OPEN_OK - 1)!=file_fd){ if(file_fd){
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
} }
const char *oldname = luaL_checklstring( L, 1, &len ); const char *oldname = luaL_checklstring( L, 1, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(oldname) == len, 1, "filename invalid"); const char *basename = vfs_basename( oldname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(oldname) == len, 1, "filename invalid");
const char *newname = luaL_checklstring( L, 2, &len ); const char *newname = luaL_checklstring( L, 2, &len );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(newname) == len, 2, "filename invalid"); basename = vfs_basename( newname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(newname) == len, 2, "filename invalid");
if(SPIFFS_OK==myspiffs_rename( oldname, newname )){ if(0 <= vfs_rename( oldname, newname )){
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
} else { } else {
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
...@@ -170,26 +252,6 @@ static int file_rename( lua_State* L ) ...@@ -170,26 +252,6 @@ static int file_rename( lua_State* L )
return 1; return 1;
} }
// Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{
u32_t total, used;
if (SPIFFS_info(&fs, &total, &used)) {
return luaL_error(L, "file system failed");
}
NODE_DBG("total: %d, used:%d\n", total, used);
if(total>0x7FFFFFFF || used>0x7FFFFFFF || used > total)
{
return luaL_error(L, "file system error");
}
lua_pushinteger(L, total-used);
lua_pushinteger(L, used);
lua_pushinteger(L, total);
return 3;
}
#endif
// g_read() // g_read()
static int file_g_read( lua_State* L, int n, int16_t end_char ) static int file_g_read( lua_State* L, int n, int16_t end_char )
{ {
...@@ -199,14 +261,14 @@ static int file_g_read( lua_State* L, int n, int16_t end_char ) ...@@ -199,14 +261,14 @@ static int file_g_read( lua_State* L, int n, int16_t end_char )
end_char = EOF; end_char = EOF;
luaL_Buffer b; luaL_Buffer b;
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
char *p = luaL_prepbuffer(&b); char *p = luaL_prepbuffer(&b);
int i; int i;
n = fs_read(file_fd, p, n); n = vfs_read(file_fd, p, n);
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
if (p[i] == end_char) if (p[i] == end_char)
{ {
...@@ -219,7 +281,7 @@ static int file_g_read( lua_State* L, int n, int16_t end_char ) ...@@ -219,7 +281,7 @@ static int file_g_read( lua_State* L, int n, int16_t end_char )
return (lua_objlen(L, -1) > 0); /* check whether read something */ return (lua_objlen(L, -1) > 0); /* check whether read something */
} }
fs_seek(file_fd, -(n - i), SEEK_CUR); vfs_lseek(file_fd, -(n - i), VFS_SEEK_CUR);
luaL_addsize(&b, i); luaL_addsize(&b, i);
luaL_pushresult(&b); /* close buffer */ luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */ return 1; /* read at least an `eol' */
...@@ -262,11 +324,11 @@ static int file_readline( lua_State* L ) ...@@ -262,11 +324,11 @@ static int file_readline( lua_State* L )
// Lua: write("string") // Lua: write("string")
static int file_write( lua_State* L ) static int file_write( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
size_t l, rl; size_t l, rl;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
rl = fs_write(file_fd, s, l); rl = vfs_write(file_fd, s, l);
if(rl==l) if(rl==l)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
...@@ -277,13 +339,13 @@ static int file_write( lua_State* L ) ...@@ -277,13 +339,13 @@ static int file_write( lua_State* L )
// Lua: writeline("string") // Lua: writeline("string")
static int file_writeline( lua_State* L ) static int file_writeline( lua_State* L )
{ {
if((FS_OPEN_OK - 1)==file_fd) if(!file_fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
size_t l, rl; size_t l, rl;
const char *s = luaL_checklstring(L, 1, &l); const char *s = luaL_checklstring(L, 1, &l);
rl = fs_write(file_fd, s, l); rl = vfs_write(file_fd, s, l);
if(rl==l){ if(rl==l){
rl = fs_write(file_fd, "\n", 1); rl = vfs_write(file_fd, "\n", 1);
if(rl==1) if(rl==1)
lua_pushboolean(L, 1); lua_pushboolean(L, 1);
else else
...@@ -295,13 +357,79 @@ static int file_writeline( lua_State* L ) ...@@ -295,13 +357,79 @@ static int file_writeline( lua_State* L )
return 1; return 1;
} }
static int file_fscfg (lua_State *L) // Lua: fsinfo()
static int file_fsinfo( lua_State* L )
{ {
lua_pushinteger (L, fs.cfg.phys_addr); u32_t total, used;
lua_pushinteger (L, fs.cfg.phys_size); if (vfs_fsinfo("", &total, &used)) {
return 2; return luaL_error(L, "file system failed");
}
NODE_DBG("total: %d, used:%d\n", total, used);
if(total>0x7FFFFFFF || used>0x7FFFFFFF || used > total)
{
return luaL_error(L, "file system error");
}
lua_pushinteger(L, total-used);
lua_pushinteger(L, used);
lua_pushinteger(L, total);
return 3;
} }
typedef struct {
vfs_vol *vol;
} volume_type;
// Lua: vol = file.mount("/SD0")
static int file_mount( lua_State *L )
{
const char *ldrv = luaL_checkstring( L, 1 );
int num = luaL_optint( L, 2, -1 );
volume_type *vol = (volume_type *)lua_newuserdata( L, sizeof( volume_type ) );
if (vol->vol = vfs_mount( ldrv, num )) {
/* set its metatable */
luaL_getmetatable(L, "vfs.vol");
lua_setmetatable(L, -2);
return 1;
} else {
// remove created userdata
lua_pop( L, 1 );
return 0;
}
}
// Lua: success = file.chdir("/SD0/")
static int file_chdir( lua_State *L )
{
const char *path = luaL_checkstring( L, 1 );
lua_pushboolean( L, 0 <= vfs_chdir( path ) );
return 1;
}
static int file_vol_umount( lua_State *L )
{
volume_type *vol = luaL_checkudata( L, 1, "file.vol" );
luaL_argcheck( L, vol, 1, "volume expected" );
lua_pushboolean( L, 0 <= vfs_umount( vol->vol ) );
// invalidate vfs descriptor, it has been free'd anyway
vol->vol = NULL;
return 1;
}
static const LUA_REG_TYPE file_vol_map[] =
{
{ LSTRKEY( "umount" ), LFUNCVAL( file_vol_umount )},
//{ LSTRKEY( "getfree" ), LFUNCVAL( file_vol_getfree )},
//{ LSTRKEY( "getlabel" ), LFUNCVAL( file_vol_getlabel )},
//{ LSTRKEY( "__gc" ), LFUNCVAL( file_vol_free ) },
{ LSTRKEY( "__index" ), LROVAL( file_vol_map ) },
{ LNILKEY, LNILVAL }
};
// Module function map // Module function map
static const LUA_REG_TYPE file_map[] = { static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "list" ), LFUNCVAL( file_list ) }, { LSTRKEY( "list" ), LFUNCVAL( file_list ) },
...@@ -311,17 +439,27 @@ static const LUA_REG_TYPE file_map[] = { ...@@ -311,17 +439,27 @@ static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) }, { LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) },
{ LSTRKEY( "read" ), LFUNCVAL( file_read ) }, { LSTRKEY( "read" ), LFUNCVAL( file_read ) },
{ LSTRKEY( "readline" ), LFUNCVAL( file_readline ) }, { LSTRKEY( "readline" ), LFUNCVAL( file_readline ) },
#ifdef BUILD_SPIFFS
{ LSTRKEY( "format" ), LFUNCVAL( file_format ) }, { LSTRKEY( "format" ), LFUNCVAL( file_format ) },
#if defined(BUILD_SPIFFS) { LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
#endif
{ LSTRKEY( "remove" ), LFUNCVAL( file_remove ) }, { LSTRKEY( "remove" ), LFUNCVAL( file_remove ) },
{ LSTRKEY( "seek" ), LFUNCVAL( file_seek ) }, { LSTRKEY( "seek" ), LFUNCVAL( file_seek ) },
{ LSTRKEY( "flush" ), LFUNCVAL( file_flush ) }, { LSTRKEY( "flush" ), LFUNCVAL( file_flush ) },
{ LSTRKEY( "rename" ), LFUNCVAL( file_rename ) }, { LSTRKEY( "rename" ), LFUNCVAL( file_rename ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
{ LSTRKEY( "exists" ), LFUNCVAL( file_exists ) }, { LSTRKEY( "exists" ), LFUNCVAL( file_exists ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "on" ), LFUNCVAL( file_on ) },
#ifdef BUILD_FATFS
{ LSTRKEY( "mount" ), LFUNCVAL( file_mount ) },
{ LSTRKEY( "chdir" ), LFUNCVAL( file_chdir ) },
#endif #endif
{ LNILKEY, LNILVAL } { LNILKEY, LNILVAL }
}; };
NODEMCU_MODULE(FILE, "file", file_map, NULL); int luaopen_file( lua_State *L ) {
luaL_rometatable( L, "file.vol", (void *)file_vol_map );
return 0;
}
NODEMCU_MODULE(FILE, "file", file_map, luaopen_file);
/*
* This module, when enabled with the LUA_USE_MODULES_GDBSTUB define causes
* the gdbstub code to be included and enabled to handle all fatal exceptions.
* This allows you to use the lx106 gdb to catch the exception and then poke
* around. You can't continue from an exception (at least not easily).
*
* This should not be included in production builds as any exception will
* put the nodemcu into a state where it is waiting for serial input and it has
* the watchdog disabled. Good for debugging. Bad for unattended operation!
*
* See the docs for more information.
*
* Philip Gladstone, N1DQ
*/
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_types.h"
#include "user_interface.h"
#include "../esp-gdbstub/gdbstub.h"
// gdbstub.brk() just executes a break instruction. Enters gdb
static int lgdbstub_break(lua_State *L) {
asm("break 0,0" ::);
return 0;
}
// gdbstub.gdboutput(1) switches the output to gdb format so that gdb can display it
static int lgdbstub_gdboutput(lua_State *L) {
gdbstub_redirect_output(lua_toboolean(L, 1));
return 0;
}
static int lgdbstub_open(lua_State *L) {
gdbstub_init();
return 0;
}
// Module function map
static const LUA_REG_TYPE gdbstub_map[] = {
{ LSTRKEY( "brk" ), LFUNCVAL( lgdbstub_break ) },
{ LSTRKEY( "gdboutput" ), LFUNCVAL( lgdbstub_gdboutput) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(GDBSTUB, "gdbstub", gdbstub_map, lgdbstub_open);
...@@ -76,7 +76,7 @@ static int http_lapi_request( lua_State *L ) ...@@ -76,7 +76,7 @@ static int http_lapi_request( lua_State *L )
http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX); http_callback_registry = luaL_ref(L, LUA_REGISTRYINDEX);
} }
http_request(url, method, headers, body, http_callback); http_request(url, method, headers, body, http_callback, 0);
return 0; return 0;
} }
......
...@@ -125,6 +125,7 @@ static void mqtt_socket_disconnected(void *arg) // tcp only ...@@ -125,6 +125,7 @@ static void mqtt_socket_disconnected(void *arg) // tcp only
mud->pesp_conn = NULL; mud->pesp_conn = NULL;
} }
mud->connected = false;
luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref);
mud->self_ref = LUA_NOREF; // unref this, and the mqtt.socket userdata will delete it self mud->self_ref = LUA_NOREF; // unref this, and the mqtt.socket userdata will delete it self
} }
...@@ -156,6 +157,14 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err) ...@@ -156,6 +157,14 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
pesp_conn->proto.tcp->local_port = espconn_port(); pesp_conn->proto.tcp->local_port = espconn_port();
socket_connect(pesp_conn); socket_connect(pesp_conn);
} else { } else {
#ifdef CLIENT_SSL_ENABLE
if (mud->secure) {
espconn_secure_disconnect(pesp_conn);
} else
#endif
{
espconn_disconnect(pesp_conn);
}
mqtt_socket_disconnected(arg); mqtt_socket_disconnected(arg);
} }
NODE_DBG("leave mqtt_socket_reconnected.\n"); NODE_DBG("leave mqtt_socket_reconnected.\n");
...@@ -804,6 +813,9 @@ static int mqtt_delete( lua_State* L ) ...@@ -804,6 +813,9 @@ static int mqtt_delete( lua_State* L )
c_free(mud->pesp_conn); c_free(mud->pesp_conn);
mud->pesp_conn = NULL; // for socket, it will free this when disconnected mud->pesp_conn = NULL; // for socket, it will free this when disconnected
} }
while(mud->mqtt_state.pending_msg_q) {
msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
}
// ---- alloc-ed in mqtt_socket_lwt() // ---- alloc-ed in mqtt_socket_lwt()
if(mud->connect_info.will_topic){ if(mud->connect_info.will_topic){
...@@ -873,8 +885,7 @@ static sint8 socket_connect(struct espconn *pesp_conn) ...@@ -873,8 +885,7 @@ static sint8 socket_connect(struct espconn *pesp_conn)
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
if(mud->secure) if(mud->secure)
{ {
espconn_secure_set_size(ESPCONN_CLIENT, 5120); /* set SSL buffer size */ espconn_status = espconn_secure_connect(pesp_conn);
espconn_status = espconn_secure_connect(pesp_conn);
} }
else else
#endif #endif
...@@ -884,7 +895,7 @@ static sint8 socket_connect(struct espconn *pesp_conn) ...@@ -884,7 +895,7 @@ static sint8 socket_connect(struct espconn *pesp_conn)
os_timer_arm(&mud->mqttTimer, 1000, 1); os_timer_arm(&mud->mqttTimer, 1000, 1);
NODE_DBG("leave socket_connect.\n"); NODE_DBG("leave socket_connect, heap = %u.\n", system_get_free_heap_size());
return espconn_status; return espconn_status;
} }
...@@ -971,22 +982,17 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -971,22 +982,17 @@ static int mqtt_socket_connect( lua_State* L )
return luaL_error(L, "already connected"); return luaL_error(L, "already connected");
} }
if(mud->pesp_conn){ //TODO: should I free tcp struct directly or ask user to call close()??? struct espconn *pesp_conn = mud->pesp_conn;
mud->pesp_conn->reverse = NULL; if(!pesp_conn) {
if(mud->pesp_conn->proto.tcp) pesp_conn = mud->pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn));
c_free(mud->pesp_conn->proto.tcp); } else {
mud->pesp_conn->proto.tcp = NULL; espconn_delete(pesp_conn);
c_free(mud->pesp_conn);
mud->pesp_conn = NULL;
} }
struct espconn *pesp_conn = NULL;
pesp_conn = mud->pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn));
if(!pesp_conn) if(!pesp_conn)
return luaL_error(L, "not enough memory"); return luaL_error(L, "not enough memory");
if (!pesp_conn->proto.tcp)
pesp_conn->proto.udp = NULL; pesp_conn->proto.tcp = (esp_tcp *)c_zalloc(sizeof(esp_tcp));
pesp_conn->proto.tcp = (esp_tcp *)c_zalloc(sizeof(esp_tcp));
if(!pesp_conn->proto.tcp){ if(!pesp_conn->proto.tcp){
c_free(pesp_conn); c_free(pesp_conn);
pesp_conn = mud->pesp_conn = NULL; pesp_conn = mud->pesp_conn = NULL;
...@@ -1021,7 +1027,8 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1021,7 +1027,8 @@ static int mqtt_socket_connect( lua_State* L )
NODE_DBG("TCP port is set: %d.\n", port); NODE_DBG("TCP port is set: %d.\n", port);
} }
pesp_conn->proto.tcp->remote_port = port; pesp_conn->proto.tcp->remote_port = port;
pesp_conn->proto.tcp->local_port = espconn_port(); if (pesp_conn->proto.tcp->local_port == 0)
pesp_conn->proto.tcp->local_port = espconn_port();
mud->mqtt_state.port = port; mud->mqtt_state.port = port;
if ( (stack<=top) && lua_isnumber(L, stack) ) if ( (stack<=top) && lua_isnumber(L, stack) )
...@@ -1121,31 +1128,33 @@ static int mqtt_socket_close( lua_State* L ) ...@@ -1121,31 +1128,33 @@ static int mqtt_socket_close( lua_State* L )
return 1; return 1;
} }
// Send disconnect message
mqtt_message_t* temp_msg = mqtt_msg_disconnect(&mud->mqtt_state.mqtt_connection);
NODE_DBG("Send MQTT disconnect infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]);
sint8 espconn_status;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
espconn_status = espconn_secure_send(mud->pesp_conn, temp_msg->data, temp_msg->length);
else
#endif
espconn_status = espconn_send(mud->pesp_conn, temp_msg->data, temp_msg->length);
mud->mqtt_state.auto_reconnect = 0; // stop auto reconnect. mud->mqtt_state.auto_reconnect = 0; // stop auto reconnect.
sint8 espconn_status = ESPCONN_CONN;
if (mud->connected) {
// Send disconnect message
mqtt_message_t* temp_msg = mqtt_msg_disconnect(&mud->mqtt_state.mqtt_connection);
NODE_DBG("Send MQTT disconnect infomation, data len: %d, d[0]=%d \r\n", temp_msg->length, temp_msg->data[0]);
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
if(mud->secure){ if(mud->secure) {
if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port) espconn_status = espconn_secure_send(mud->pesp_conn, temp_msg->data, temp_msg->length);
espconn_status |= espconn_secure_disconnect(mud->pesp_conn); if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port)
} espconn_status |= espconn_secure_disconnect(mud->pesp_conn);
else } else
#endif #endif
{ {
if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port) espconn_status = espconn_send(mud->pesp_conn, temp_msg->data, temp_msg->length);
espconn_status |= espconn_disconnect(mud->pesp_conn); if(mud->pesp_conn->proto.tcp->remote_port || mud->pesp_conn->proto.tcp->local_port)
espconn_status |= espconn_disconnect(mud->pesp_conn);
}
} }
mud->connected = 0;
while (mud->mqtt_state.pending_msg_q) {
msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
}
NODE_DBG("leave mqtt_socket_close.\n"); NODE_DBG("leave mqtt_socket_close.\n");
if (espconn_status == ESPCONN_OK) { if (espconn_status == ESPCONN_OK) {
......
...@@ -34,7 +34,6 @@ static int expose_array(lua_State* L, char *array, unsigned short len); ...@@ -34,7 +34,6 @@ static int expose_array(lua_State* L, char *array, unsigned short len);
#define MAX_SOCKET 5 #define MAX_SOCKET 5
static int socket_num = 0; static int socket_num = 0;
static int socket[MAX_SOCKET]; static int socket[MAX_SOCKET];
static lua_State *gL = NULL;
static int tcpserver_cb_connect_ref = LUA_NOREF; // for tcp server connected callback static int tcpserver_cb_connect_ref = LUA_NOREF; // for tcp server connected callback
static uint16_t tcp_server_timeover = 30; static uint16_t tcp_server_timeover = 30;
...@@ -65,8 +64,7 @@ static void net_server_disconnected(void *arg) // for tcp server only ...@@ -65,8 +64,7 @@ static void net_server_disconnected(void *arg) // for tcp server only
lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse; lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse;
if(nud == NULL) if(nud == NULL)
return; return;
if(gL == NULL) lua_State *L = lua_getstate();
return;
#if 0 #if 0
char temp[20] = {0}; char temp[20] = {0};
c_sprintf(temp, IPSTR, IP2STR( &(pesp_conn->proto.tcp->remote_ip) ) ); c_sprintf(temp, IPSTR, IP2STR( &(pesp_conn->proto.tcp->remote_ip) ) );
...@@ -78,25 +76,25 @@ static void net_server_disconnected(void *arg) // for tcp server only ...@@ -78,25 +76,25 @@ static void net_server_disconnected(void *arg) // for tcp server only
#endif #endif
if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF) if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF)
{ {
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_disconnect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(gL, 1, 0); lua_call(L, 1, 0);
} }
int i; int i;
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
for(i=0;i<MAX_SOCKET;i++){ for(i=0;i<MAX_SOCKET;i++){
if( (LUA_NOREF!=socket[i]) && (socket[i] == nud->self_ref) ){ if( (LUA_NOREF!=socket[i]) && (socket[i] == nud->self_ref) ){
// found the saved client // found the saved client
nud->pesp_conn->reverse = NULL; nud->pesp_conn->reverse = NULL;
nud->pesp_conn = NULL; // the espconn is made by low level sdk, do not need to free, delete() will not free it. nud->pesp_conn = NULL; // the espconn is made by low level sdk, do not need to free, delete() will not free it.
nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self
luaL_unref(gL, LUA_REGISTRYINDEX, socket[i]); luaL_unref(L, LUA_REGISTRYINDEX, socket[i]);
socket[i] = LUA_NOREF; socket[i] = LUA_NOREF;
socket_num--; socket_num--;
break; break;
} }
} }
lua_gc(gL, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
} }
static void net_socket_disconnected(void *arg) // tcp only static void net_socket_disconnected(void *arg) // tcp only
...@@ -108,11 +106,12 @@ static void net_socket_disconnected(void *arg) // tcp only ...@@ -108,11 +106,12 @@ static void net_socket_disconnected(void *arg) // tcp only
lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse; lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse;
if(nud == NULL) if(nud == NULL)
return; return;
lua_State *L = lua_getstate();
if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF) if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF)
{ {
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_disconnect_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(gL, 1, 0); lua_call(L, 1, 0);
} }
if(pesp_conn->proto.tcp) if(pesp_conn->proto.tcp)
...@@ -121,12 +120,12 @@ static void net_socket_disconnected(void *arg) // tcp only ...@@ -121,12 +120,12 @@ static void net_socket_disconnected(void *arg) // tcp only
if(nud->pesp_conn) if(nud->pesp_conn)
c_free(nud->pesp_conn); c_free(nud->pesp_conn);
nud->pesp_conn = NULL; // espconn is already disconnected nud->pesp_conn = NULL; // espconn is already disconnected
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
if(nud->self_ref != LUA_NOREF){ if(nud->self_ref != LUA_NOREF){
luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref); luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self
} }
lua_gc(gL, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
} }
static void net_server_reconnected(void *arg, sint8_t err) static void net_server_reconnected(void *arg, sint8_t err)
...@@ -154,15 +153,16 @@ static void net_socket_received(void *arg, char *pdata, unsigned short len) ...@@ -154,15 +153,16 @@ static void net_socket_received(void *arg, char *pdata, unsigned short len)
return; return;
if(nud->self_ref == LUA_NOREF) if(nud->self_ref == LUA_NOREF)
return; return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_receive_ref); lua_State *L = lua_getstate();
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_receive_ref);
// expose_array(gL, pdata, len); lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua
// expose_array(L, pdata, len);
// *(pdata+len) = 0; // *(pdata+len) = 0;
// NODE_DBG(pdata); // NODE_DBG(pdata);
// NODE_DBG("\n"); // NODE_DBG("\n");
lua_pushlstring(gL, pdata, len); lua_pushlstring(L, pdata, len);
// lua_pushinteger(gL, len); // lua_pushinteger(L, len);
lua_call(gL, 2, 0); lua_call(L, 2, 0);
} }
static void net_socket_sent(void *arg) static void net_socket_sent(void *arg)
...@@ -178,9 +178,10 @@ static void net_socket_sent(void *arg) ...@@ -178,9 +178,10 @@ static void net_socket_sent(void *arg)
return; return;
if(nud->self_ref == LUA_NOREF) if(nud->self_ref == LUA_NOREF)
return; return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_send_ref); lua_State *L = lua_getstate();
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_send_ref);
lua_call(gL, 1, 0); lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua
lua_call(L, 1, 0);
} }
static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
...@@ -205,34 +206,16 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -205,34 +206,16 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
NODE_DBG("self_ref null.\n"); NODE_DBG("self_ref null.\n");
return; return;
} }
/* original
if(ipaddr == NULL)
{
NODE_ERR( "DNS Fail!\n" );
goto end;
}
// ipaddr->addr is a uint32_t ip
char ip_str[20];
c_memset(ip_str, 0, sizeof(ip_str));
if(ipaddr->addr != 0)
{
c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr)));
}
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function lua_State *L = lua_getstate();
//lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua
lua_pushstring(gL, ip_str); // the ip para
*/
// "enhanced" lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); // the callback function
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua
if(ipaddr == NULL) if(ipaddr == NULL)
{ {
NODE_DBG( "DNS Fail!\n" ); NODE_DBG( "DNS Fail!\n" );
lua_pushnil(gL); lua_pushnil(L);
}else{ }else{
// ipaddr->addr is a uint32_t ip // ipaddr->addr is a uint32_t ip
char ip_str[20]; char ip_str[20];
...@@ -241,21 +224,21 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -241,21 +224,21 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
{ {
c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr))); c_sprintf(ip_str, IPSTR, IP2STR(&(ipaddr->addr)));
} }
lua_pushstring(gL, ip_str); // the ip para lua_pushstring(L, ip_str); // the ip para
} }
// "enhanced" end // "enhanced" end
lua_call(gL, 2, 0); lua_call(L, 2, 0);
end: end:
if((pesp_conn->type == ESPCONN_TCP && pesp_conn->proto.tcp->remote_port == 0) if((pesp_conn->type == ESPCONN_TCP && pesp_conn->proto.tcp->remote_port == 0)
|| (pesp_conn->type == ESPCONN_UDP && pesp_conn->proto.udp->remote_port == 0) ){ || (pesp_conn->type == ESPCONN_UDP && pesp_conn->proto.udp->remote_port == 0) ){
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
if(nud->self_ref != LUA_NOREF){ if(nud->self_ref != LUA_NOREF){
luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref); luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self
} }
lua_gc(gL, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
} }
} }
...@@ -295,25 +278,24 @@ static void net_server_connected(void *arg) // for tcp only ...@@ -295,25 +278,24 @@ static void net_server_connected(void *arg) // for tcp only
if(tcpserver_cb_connect_ref == LUA_NOREF) if(tcpserver_cb_connect_ref == LUA_NOREF)
return; return;
if(!gL) lua_State *L = lua_getstate();
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, tcpserver_cb_connect_ref); // get function lua_rawgeti(L, LUA_REGISTRYINDEX, tcpserver_cb_connect_ref); // get function
// create a new client object // create a new client object
skt = (lnet_userdata *)lua_newuserdata(gL, sizeof(lnet_userdata)); skt = (lnet_userdata *)lua_newuserdata(L, sizeof(lnet_userdata));
if(!skt){ if(!skt){
NODE_ERR("can't newudata\n"); NODE_ERR("can't newudata\n");
lua_pop(gL, 1); lua_pop(L, 1);
return; return;
} }
// set its metatable // set its metatable
luaL_getmetatable(gL, "net.socket"); luaL_getmetatable(L, "net.socket");
lua_setmetatable(gL, -2); lua_setmetatable(L, -2);
// pre-initialize it, in case of errors // pre-initialize it, in case of errors
skt->self_ref = LUA_NOREF; skt->self_ref = LUA_NOREF;
lua_pushvalue(gL, -1); // copy the top of stack lua_pushvalue(L, -1); // copy the top of stack
skt->self_ref = luaL_ref(gL, LUA_REGISTRYINDEX); // ref to it self, for module api to find the userdata skt->self_ref = luaL_ref(L, LUA_REGISTRYINDEX); // ref to it self, for module api to find the userdata
socket[i] = skt->self_ref; // save to socket array socket[i] = skt->self_ref; // save to socket array
socket_num++; socket_num++;
skt->cb_connect_ref = LUA_NOREF; // this socket already connected skt->cb_connect_ref = LUA_NOREF; // this socket already connected
...@@ -337,7 +319,7 @@ static void net_server_connected(void *arg) // for tcp only ...@@ -337,7 +319,7 @@ static void net_server_connected(void *arg) // for tcp only
espconn_regist_reconcb(pesp_conn, net_server_reconnected); espconn_regist_reconcb(pesp_conn, net_server_reconnected);
// now socket[i] has the client ref, and stack top has the userdata // now socket[i] has the client ref, and stack top has the userdata
lua_call(gL, 1, 0); // function(conn) lua_call(L, 1, 0); // function(conn)
} }
static void net_socket_connected(void *arg) static void net_socket_connected(void *arg)
...@@ -358,9 +340,10 @@ static void net_socket_connected(void *arg) ...@@ -358,9 +340,10 @@ static void net_socket_connected(void *arg)
return; return;
if(nud->self_ref == LUA_NOREF) if(nud->self_ref == LUA_NOREF)
return; return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_connect_ref); lua_State *L = lua_getstate();
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_connect_ref);
lua_call(gL, 1, 0); lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(L, 1, 0);
} }
// Lua: s = net.create(type, secure/timeout, function(conn)) // Lua: s = net.create(type, secure/timeout, function(conn))
...@@ -492,8 +475,6 @@ static int net_create( lua_State* L, const char* mt ) ...@@ -492,8 +475,6 @@ static int net_create( lua_State* L, const char* mt )
pUdpServer = pesp_conn; pUdpServer = pesp_conn;
} }
gL = L; // global L for net module.
// if call back function is specified, call it with para userdata // if call back function is specified, call it with para userdata
// luaL_checkanyfunction(L, 2); // luaL_checkanyfunction(L, 2);
if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){ if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
...@@ -575,12 +556,12 @@ static int net_delete( lua_State* L, const char* mt ) ...@@ -575,12 +556,12 @@ static int net_delete( lua_State* L, const char* mt )
luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_dns_found_ref); luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_dns_found_ref);
nud->cb_dns_found_ref = LUA_NOREF; nud->cb_dns_found_ref = LUA_NOREF;
} }
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
if(LUA_NOREF!=nud->self_ref){ if(LUA_NOREF!=nud->self_ref){
luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref); luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF; nud->self_ref = LUA_NOREF;
} }
lua_gc(gL, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
return 0; return 0;
} }
...@@ -596,7 +577,6 @@ static void socket_connect(struct espconn *pesp_conn) ...@@ -596,7 +577,6 @@ static void socket_connect(struct espconn *pesp_conn)
{ {
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
if(nud->secure){ if(nud->secure){
espconn_secure_set_size(ESPCONN_CLIENT, 5120); /* set SSL buffer size */
espconn_secure_connect(pesp_conn); espconn_secure_connect(pesp_conn);
} }
else else
...@@ -625,19 +605,18 @@ static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -625,19 +605,18 @@ static void socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse; lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse;
if(nud == NULL) if(nud == NULL)
return; return;
if(gL == NULL) lua_State *L = lua_getstate();
return;
if(ipaddr == NULL) if(ipaddr == NULL)
{ {
dns_reconn_count++; dns_reconn_count++;
if( dns_reconn_count >= 5 ){ if( dns_reconn_count >= 5 ){
NODE_ERR( "DNS Fail!\n" ); NODE_ERR( "DNS Fail!\n" );
lua_gc(gL, LUA_GCSTOP, 0); lua_gc(L, LUA_GCSTOP, 0);
if(nud->self_ref != LUA_NOREF){ if(nud->self_ref != LUA_NOREF){
luaL_unref(gL, LUA_REGISTRYINDEX, nud->self_ref); luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self nud->self_ref = LUA_NOREF; // unref this, and the net.socket userdata will delete it self
} }
lua_gc(gL, LUA_GCRESTART, 0); lua_gc(L, LUA_GCRESTART, 0);
return; return;
} }
NODE_ERR( "DNS retry %d!\n", dns_reconn_count ); NODE_ERR( "DNS retry %d!\n", dns_reconn_count );
...@@ -1175,8 +1154,8 @@ static int net_dns_static( lua_State* L ) ...@@ -1175,8 +1154,8 @@ static int net_dns_static( lua_State* L )
lua_pushinteger(L, UDP); // we are going to create a new dummy UDP socket lua_pushinteger(L, UDP); // we are going to create a new dummy UDP socket
lua_call(L,1,1);// after this the stack should have a socket lua_call(L,1,1);// after this the stack should have a socket
lua_rawgeti(gL, LUA_REGISTRYINDEX, rdom); // load domain back to the stack lua_rawgeti(L, LUA_REGISTRYINDEX, rdom); // load domain back to the stack
lua_rawgeti(gL, LUA_REGISTRYINDEX, rfunc); // load the callback function back to the stack lua_rawgeti(L, LUA_REGISTRYINDEX, rfunc); // load the callback function back to the stack
luaL_unref(L, LUA_REGISTRYINDEX, rdom); //free reference luaL_unref(L, LUA_REGISTRYINDEX, rdom); //free reference
luaL_unref(L, LUA_REGISTRYINDEX, rfunc); //free reference luaL_unref(L, LUA_REGISTRYINDEX, rfunc); //free reference
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "driver/uart.h" #include "driver/uart.h"
#include "user_interface.h" #include "user_interface.h"
#include "flash_api.h" #include "flash_api.h"
#include "flash_fs.h" #include "vfs.h"
#include "user_version.h" #include "user_version.h"
#include "rom.h" #include "rom.h"
#include "task/task.h" #include "task/task.h"
...@@ -146,160 +146,6 @@ static int node_heap( lua_State* L ) ...@@ -146,160 +146,6 @@ static int node_heap( lua_State* L )
return 1; return 1;
} }
#ifdef DEVKIT_VERSION_0_9
static int led_high_count = LED_HIGH_COUNT_DEFAULT;
static int led_low_count = LED_LOW_COUNT_DEFAULT;
static int led_count = 0;
static int key_press_count = 0;
static bool key_short_pressed = false;
static bool key_long_pressed = false;
static os_timer_t keyled_timer;
static int long_key_ref = LUA_NOREF;
static int short_key_ref = LUA_NOREF;
static void default_long_press(void *arg) {
if (led_high_count == 12 && led_low_count == 12) {
led_low_count = led_high_count = 6;
} else {
led_low_count = led_high_count = 12;
}
// led_high_count = 1000 / READLINE_INTERVAL;
// led_low_count = 1000 / READLINE_INTERVAL;
// NODE_DBG("default_long_press is called. hc: %d, lc: %d\n", led_high_count, led_low_count);
}
static void default_short_press(void *arg) {
system_restart();
}
static void key_long_press(void *arg) {
lua_State *L = lua_getstate();
NODE_DBG("key_long_press is called.\n");
if (long_key_ref == LUA_NOREF) {
default_long_press(arg);
return;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, long_key_ref);
lua_call(L, 0, 0);
}
static void key_short_press(void *arg) {
lua_State *L = lua_getstate();
NODE_DBG("key_short_press is called.\n");
if (short_key_ref == LUA_NOREF) {
default_short_press(arg);
return;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, short_key_ref);
lua_call(L, 0, 0);
}
static void update_key_led (void *p)
{
(void)p;
uint8_t temp = 1, level = 1;
led_count++;
if(led_count>led_low_count+led_high_count){
led_count = 0; // reset led_count, the level still high
} else if(led_count>led_low_count && led_count <=led_high_count+led_low_count){
level = 1; // output high level
} else if(led_count<=led_low_count){
level = 0; // output low level
}
temp = platform_key_led(level);
if(temp == 0){ // key is pressed
key_press_count++;
if(key_press_count>=KEY_LONG_COUNT){
// key_long_press(NULL);
key_long_pressed = true;
key_short_pressed = false;
// key_press_count = 0;
} else if(key_press_count>=KEY_SHORT_COUNT){ // < KEY_LONG_COUNT
// key_short_press(NULL);
key_short_pressed = true;
}
}else{ // key is released
key_press_count = 0;
if(key_long_pressed){
key_long_press(NULL);
key_long_pressed = false;
}
if(key_short_pressed){
key_short_press(NULL);
key_short_pressed = false;
}
}
}
static void prime_keyled_timer (void)
{
os_timer_disarm (&keyled_timer);
os_timer_setfn (&keyled_timer, update_key_led, 0);
os_timer_arm (&keyled_timer, KEYLED_INTERVAL, 1);
}
// Lua: led(low, high)
static int node_led( lua_State* L )
{
int low, high;
if ( lua_isnumber(L, 1) )
{
low = lua_tointeger(L, 1);
if ( low < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
low = LED_LOW_COUNT_DEFAULT; // default to LED_LOW_COUNT_DEFAULT
}
if ( lua_isnumber(L, 2) )
{
high = lua_tointeger(L, 2);
if ( high < 0 ) {
return luaL_error( L, "wrong arg type" );
}
} else {
high = LED_HIGH_COUNT_DEFAULT; // default to LED_HIGH_COUNT_DEFAULT
}
led_high_count = (uint32_t)high / READLINE_INTERVAL;
led_low_count = (uint32_t)low / READLINE_INTERVAL;
prime_keyled_timer();
return 0;
}
// Lua: key(type, function)
static int node_key( lua_State* L )
{
int *ref = NULL;
size_t sl;
const char *str = luaL_checklstring( L, 1, &sl );
if (str == NULL)
return luaL_error( L, "wrong arg type" );
if (sl == 5 && c_strcmp(str, "short") == 0) {
ref = &short_key_ref;
} else if (sl == 4 && c_strcmp(str, "long") == 0) {
ref = &long_key_ref;
} else {
ref = &short_key_ref;
}
// luaL_checkanyfunction(L, 2);
if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION) {
lua_pushvalue(L, 2); // copy argument (func) to the top of stack
if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else { // unref the key press function
if (*ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, *ref);
*ref = LUA_NOREF;
}
prime_keyled_timer();
return 0;
}
#endif
extern lua_Load gLoad; extern lua_Load gLoad;
extern bool user_process_input(bool force); extern bool user_process_input(bool force);
// Lua: input("string") // Lua: input("string")
...@@ -333,7 +179,7 @@ void output_redirect(const char *str) { ...@@ -333,7 +179,7 @@ void output_redirect(const char *str) {
// return; // return;
// } // }
if (output_redir_ref == LUA_NOREF || !L) { if (output_redir_ref == LUA_NOREF) {
uart0_sendStr(str); uart0_sendStr(str);
return; return;
} }
...@@ -380,11 +226,11 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) ...@@ -380,11 +226,11 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
{ {
UNUSED(L); UNUSED(L);
int file_fd = *( (int *)u ); int file_fd = *( (int *)u );
if ((FS_OPEN_OK - 1) == file_fd) if (!file_fd)
return 1; return 1;
NODE_DBG("get fd:%d,size:%d\n", file_fd, size); NODE_DBG("get fd:%d,size:%d\n", file_fd, size);
if (size != 0 && (size != fs_write(file_fd, (const char *)p, size)) ) if (size != 0 && (size != vfs_write(file_fd, (const char *)p, size)) )
return 1; return 1;
NODE_DBG("write fd:%d,size:%d\n", file_fd, size); NODE_DBG("write fd:%d,size:%d\n", file_fd, size);
return 0; return 0;
...@@ -395,23 +241,26 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) ...@@ -395,23 +241,26 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
static int node_compile( lua_State* L ) static int node_compile( lua_State* L )
{ {
Proto* f; Proto* f;
int file_fd = FS_OPEN_OK - 1; int file_fd = 0;
size_t len; size_t len;
const char *fname = luaL_checklstring( L, 1, &len ); const char *fname = luaL_checklstring( L, 1, &len );
if ( len >= FS_NAME_MAX_LENGTH ) const char *basename = vfs_basename( fname );
return luaL_error(L, "filename too long"); luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
char output[FS_NAME_MAX_LENGTH]; char *output = luaM_malloc( L, len+1 );
c_strcpy(output, fname); c_strcpy(output, fname);
// check here that filename end with ".lua". // check here that filename end with ".lua".
if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) {
luaM_free( L, output );
return luaL_error(L, "not a .lua file"); return luaL_error(L, "not a .lua file");
}
output[c_strlen(output) - 2] = 'c'; output[c_strlen(output) - 2] = 'c';
output[c_strlen(output) - 1] = '\0'; output[c_strlen(output) - 1] = '\0';
NODE_DBG(output); NODE_DBG(output);
NODE_DBG("\n"); NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) { if (luaL_loadfsfile(L, fname) != 0) {
luaM_free( L, output );
return luaL_error(L, lua_tostring(L, -1)); return luaL_error(L, lua_tostring(L, -1));
} }
...@@ -419,9 +268,10 @@ static int node_compile( lua_State* L ) ...@@ -419,9 +268,10 @@ static int node_compile( lua_State* L )
int stripping = 1; /* strip debug information? */ int stripping = 1; /* strip debug information? */
file_fd = fs_open(output, fs_mode2flag("w+")); file_fd = vfs_open(output, "w+");
if (file_fd < FS_OPEN_OK) if (!file_fd)
{ {
luaM_free( L, output );
return luaL_error(L, "cannot open/write to file"); return luaL_error(L, "cannot open/write to file");
} }
...@@ -429,12 +279,13 @@ static int node_compile( lua_State* L ) ...@@ -429,12 +279,13 @@ static int node_compile( lua_State* L )
int result = luaU_dump(L, f, writer, &file_fd, stripping); int result = luaU_dump(L, f, writer, &file_fd, stripping);
lua_unlock(L); lua_unlock(L);
if (fs_flush(file_fd) < 0) { // result codes aren't propagated by flash_fs.h if (vfs_flush(file_fd) != VFS_RES_OK) {
// overwrite Lua error, like writer() does in case of a file io error // overwrite Lua error, like writer() does in case of a file io error
result = 1; result = 1;
} }
fs_close(file_fd); vfs_close(file_fd);
file_fd = FS_OPEN_OK - 1; file_fd = 0;
luaM_free( L, output );
if (result == LUA_ERR_CC_INTOVERFLOW) { if (result == LUA_ERR_CC_INTOVERFLOW) {
return luaL_error(L, "value too big or small for target integer type"); return luaL_error(L, "value too big or small for target integer type");
...@@ -643,10 +494,6 @@ static const LUA_REG_TYPE node_map[] = ...@@ -643,10 +494,6 @@ static const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) }, { LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) }, { LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) }, { LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
#ifdef DEVKIT_VERSION_0_9
{ LSTRKEY( "key" ), LFUNCVAL( node_key ) },
{ LSTRKEY( "led" ), LFUNCVAL( node_led ) },
#endif
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) }, { LSTRKEY( "input" ), LFUNCVAL( node_input ) },
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) }, { LSTRKEY( "output" ), LFUNCVAL( node_output ) },
// Moved to adc module, use adc.readvdd33() // Moved to adc module, use adc.readvdd33()
......
...@@ -204,7 +204,7 @@ static void on_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_a ...@@ -204,7 +204,7 @@ static void on_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_a
(void)port; (void)port;
sntp_dbg("sntp: on_recv\n"); sntp_dbg("sntp: on_recv\n");
lua_State *L = arg; lua_State *L = lua_getstate();
if (!state || state->pcb != pcb) if (!state || state->pcb != pcb)
{ {
......
...@@ -309,7 +309,7 @@ static int b_unpack (lua_State *L) { ...@@ -309,7 +309,7 @@ static int b_unpack (lua_State *L) {
size_t size = optsize(L, opt, &fmt); size_t size = optsize(L, opt, &fmt);
pos += gettoalign(pos, &h, opt, size); pos += gettoalign(pos, &h, opt, size);
luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); luaL_argcheck(L, pos+size <= ld, 2, "data string too short");
luaL_checkstack(L, 1, "too many results"); luaL_checkstack(L, 2, "too many results");
switch (opt) { switch (opt) {
case 'b': case 'B': case 'h': case 'H': case 'b': case 'B': case 'h': case 'H':
case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */ case 'l': case 'L': case 'T': case 'i': case 'I': { /* integer types */
......
...@@ -71,7 +71,7 @@ static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF); ...@@ -71,7 +71,7 @@ static const char* MAX_TIMEOUT_ERR_STR = "Range: 1-"STRINGIFY(MAX_TIMEOUT_DEF);
typedef struct{ typedef struct{
os_timer_t os; os_timer_t os;
sint32_t lua_ref; sint32_t lua_ref, self_ref;
uint32_t interval; uint32_t interval;
uint8_t mode; uint8_t mode;
}timer_struct_t; }timer_struct_t;
...@@ -95,11 +95,17 @@ static timer_struct_t alarm_timers[NUM_TMR]; ...@@ -95,11 +95,17 @@ static timer_struct_t alarm_timers[NUM_TMR];
static os_timer_t rtc_timer; static os_timer_t rtc_timer;
static void alarm_timer_common(void* arg){ static void alarm_timer_common(void* arg){
timer_t tmr = &alarm_timers[(uint32_t)arg]; timer_t tmr = (timer_t)arg;
lua_State* L = lua_getstate(); lua_State* L = lua_getstate();
if(tmr->lua_ref == LUA_NOREF) if(tmr->lua_ref == LUA_NOREF)
return; return;
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->lua_ref);
if (tmr->self_ref == LUA_REFNIL) {
uint32_t id = tmr - alarm_timers;
lua_pushinteger(L, id);
} else {
lua_rawgeti(L, LUA_REGISTRYINDEX, tmr->self_ref);
}
//if the timer was set to single run we clean up after it //if the timer was set to single run we clean up after it
if(tmr->mode == TIMER_MODE_SINGLE){ if(tmr->mode == TIMER_MODE_SINGLE){
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref); luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
...@@ -108,7 +114,11 @@ static void alarm_timer_common(void* arg){ ...@@ -108,7 +114,11 @@ static void alarm_timer_common(void* arg){
}else if(tmr->mode == TIMER_MODE_SEMI){ }else if(tmr->mode == TIMER_MODE_SEMI){
tmr->mode |= TIMER_IDLE_FLAG; tmr->mode |= TIMER_IDLE_FLAG;
} }
lua_call(L, 0, 0); if (tmr->mode != TIMER_MODE_AUTO && tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
lua_call(L, 1, 0);
} }
// Lua: tmr.delay( us ) // Lua: tmr.delay( us )
...@@ -135,20 +145,32 @@ static int tmr_now(lua_State* L){ ...@@ -135,20 +145,32 @@ static int tmr_now(lua_State* L){
return 1; return 1;
} }
// Lua: tmr.register( id, interval, mode, function ) static timer_t tmr_get( lua_State *L, int stack ) {
// Deprecated: static 0-6 timers control by index.
luaL_argcheck(L, (lua_isuserdata(L, stack) || lua_isnumber(L, stack)), 1, "timer object or numerical ID expected");
if (lua_isuserdata(L, stack)) {
return (timer_t)luaL_checkudata(L, stack, "tmr.timer");
} else {
uint32_t id = luaL_checkinteger(L, 1);
luaL_argcheck(L, platform_tmr_exists(id), 1, "invalid timer index");
return &alarm_timers[id];
}
return 0;
}
// Lua: tmr.register( id / ref, interval, mode, function )
static int tmr_register(lua_State* L){ static int tmr_register(lua_State* L){
uint32_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
uint32_t interval = luaL_checkinteger(L, 2); uint32_t interval = luaL_checkinteger(L, 2);
uint8_t mode = luaL_checkinteger(L, 3); uint8_t mode = luaL_checkinteger(L, 3);
//Check if provided parameters are valid
MOD_CHECK_ID(tmr, id);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
luaL_argcheck(L, (mode == TIMER_MODE_SINGLE || mode == TIMER_MODE_SEMI || mode == TIMER_MODE_AUTO), 3, "Invalid mode"); luaL_argcheck(L, (mode == TIMER_MODE_SINGLE || mode == TIMER_MODE_SEMI || mode == TIMER_MODE_AUTO), 3, "Invalid mode");
luaL_argcheck(L, (lua_type(L, 4) == LUA_TFUNCTION || lua_type(L, 4) == LUA_TLIGHTFUNCTION), 4, "Must be function"); luaL_argcheck(L, (lua_type(L, 4) == LUA_TFUNCTION || lua_type(L, 4) == LUA_TLIGHTFUNCTION), 4, "Must be function");
//get the lua function reference //get the lua function reference
lua_pushvalue(L, 4); lua_pushvalue(L, 4);
sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
timer_t tmr = &alarm_timers[id];
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os); ets_timer_disarm(&tmr->os);
//there was a bug in this part, the second part of the following condition was missing //there was a bug in this part, the second part of the following condition was missing
...@@ -157,15 +179,19 @@ static int tmr_register(lua_State* L){ ...@@ -157,15 +179,19 @@ static int tmr_register(lua_State* L){
tmr->lua_ref = ref; tmr->lua_ref = ref;
tmr->mode = mode|TIMER_IDLE_FLAG; tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval; tmr->interval = interval;
ets_timer_setfn(&tmr->os, alarm_timer_common, (void*)id); ets_timer_setfn(&tmr->os, alarm_timer_common, tmr);
return 0; return 0;
} }
// Lua: tmr.start( id ) // Lua: tmr.start( id / ref )
static int tmr_start(lua_State* L){ static int tmr_start(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id]; if (tmr->self_ref == LUA_NOREF) {
lua_pushvalue(L, 1);
tmr->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
//we return false if the timer is not idle //we return false if the timer is not idle
if(!(tmr->mode&TIMER_IDLE_FLAG)){ if(!(tmr->mode&TIMER_IDLE_FLAG)){
lua_pushboolean(L, 0); lua_pushboolean(L, 0);
...@@ -177,17 +203,21 @@ static int tmr_start(lua_State* L){ ...@@ -177,17 +203,21 @@ static int tmr_start(lua_State* L){
return 1; return 1;
} }
// Lua: tmr.alarm( id, interval, repeat, function ) // Lua: tmr.alarm( id / ref, interval, repeat, function )
static int tmr_alarm(lua_State* L){ static int tmr_alarm(lua_State* L){
tmr_register(L); tmr_register(L);
return tmr_start(L); return tmr_start(L);
} }
// Lua: tmr.stop( id ) // Lua: tmr.stop( id / ref )
static int tmr_stop(lua_State* L){ static int tmr_stop(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id]; if (tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
//we return false if the timer is idle (of not registered) //we return false if the timer is idle (of not registered)
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){ if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){
tmr->mode |= TIMER_IDLE_FLAG; tmr->mode |= TIMER_IDLE_FLAG;
...@@ -199,11 +229,15 @@ static int tmr_stop(lua_State* L){ ...@@ -199,11 +229,15 @@ static int tmr_stop(lua_State* L){
return 1; return 1;
} }
// Lua: tmr.unregister( id ) // Lua: tmr.unregister( id / ref )
static int tmr_unregister(lua_State* L){ static int tmr_unregister(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id]; if (tmr->self_ref != LUA_REFNIL) {
luaL_unref(L, LUA_REGISTRYINDEX, tmr->self_ref);
tmr->self_ref = LUA_NOREF;
}
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF) if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os); ets_timer_disarm(&tmr->os);
if(tmr->lua_ref != LUA_NOREF) if(tmr->lua_ref != LUA_NOREF)
...@@ -213,13 +247,12 @@ static int tmr_unregister(lua_State* L){ ...@@ -213,13 +247,12 @@ static int tmr_unregister(lua_State* L){
return 0; return 0;
} }
// Lua: tmr.interval( id, interval ) // Lua: tmr.interval( id / ref, interval )
static int tmr_interval(lua_State* L){ static int tmr_interval(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
uint32_t interval = luaL_checkinteger(L, 2); uint32_t interval = luaL_checkinteger(L, 2);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR); luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
if(tmr->mode != TIMER_MODE_OFF){ if(tmr->mode != TIMER_MODE_OFF){
tmr->interval = interval; tmr->interval = interval;
if(!(tmr->mode&TIMER_IDLE_FLAG)){ if(!(tmr->mode&TIMER_IDLE_FLAG)){
...@@ -230,11 +263,10 @@ static int tmr_interval(lua_State* L){ ...@@ -230,11 +263,10 @@ static int tmr_interval(lua_State* L){
return 0; return 0;
} }
// Lua: tmr.state( id ) // Lua: tmr.state( id / ref )
static int tmr_state(lua_State* L){ static int tmr_state(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1); timer_t tmr = tmr_get(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
if(tmr->mode == TIMER_MODE_OFF){ if(tmr->mode == TIMER_MODE_OFF){
lua_pushnil(L); lua_pushnil(L);
return 1; return 1;
...@@ -307,8 +339,34 @@ static int tmr_softwd( lua_State* L ){ ...@@ -307,8 +339,34 @@ static int tmr_softwd( lua_State* L ){
return 0; return 0;
} }
// Lua: tmr.create()
static int tmr_create( lua_State *L ) {
timer_t ud = (timer_t)lua_newuserdata(L, sizeof(timer_struct_t));
if (!ud) return luaL_error(L, "not enough memory");
luaL_getmetatable(L, "tmr.timer");
lua_setmetatable(L, -2);
ud->lua_ref = LUA_NOREF;
ud->self_ref = LUA_NOREF;
ud->mode = TIMER_MODE_OFF;
ets_timer_disarm(&ud->os);
return 1;
}
// Module function map // Module function map
static const LUA_REG_TYPE tmr_dyn_map[] = {
{ LSTRKEY( "register" ), LFUNCVAL( tmr_register ) },
{ LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) },
{ LSTRKEY( "start" ), LFUNCVAL( tmr_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval) },
{ LSTRKEY( "__gc" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "__index" ), LROVAL( tmr_dyn_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE tmr_map[] = { static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) }, { LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) }, { LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
...@@ -321,7 +379,8 @@ static const LUA_REG_TYPE tmr_map[] = { ...@@ -321,7 +379,8 @@ static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) }, { LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) }, { LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL( tmr_state ) }, { LSTRKEY( "state" ), LFUNCVAL( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL( tmr_interval) }, { LSTRKEY( "interval" ), LFUNCVAL( tmr_interval ) },
{ LSTRKEY( "create" ), LFUNCVAL( tmr_create ) },
{ LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) }, { LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) },
{ LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) }, { LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) },
{ LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) }, { LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) },
...@@ -330,8 +389,12 @@ static const LUA_REG_TYPE tmr_map[] = { ...@@ -330,8 +389,12 @@ static const LUA_REG_TYPE tmr_map[] = {
int luaopen_tmr( lua_State *L ){ int luaopen_tmr( lua_State *L ){
int i; int i;
luaL_rometatable(L, "tmr.timer", (void *)tmr_dyn_map);
for(i=0; i<NUM_TMR; i++){ for(i=0; i<NUM_TMR; i++){
alarm_timers[i].lua_ref = LUA_NOREF; alarm_timers[i].lua_ref = LUA_NOREF;
alarm_timers[i].self_ref = LUA_REFNIL;
alarm_timers[i].mode = TIMER_MODE_OFF; alarm_timers[i].mode = TIMER_MODE_OFF;
ets_timer_disarm(&alarm_timers[i].os); ets_timer_disarm(&alarm_timers[i].os);
} }
...@@ -341,7 +404,7 @@ int luaopen_tmr( lua_State *L ){ ...@@ -341,7 +404,7 @@ int luaopen_tmr( lua_State *L ){
ets_timer_disarm(&rtc_timer); ets_timer_disarm(&rtc_timer);
ets_timer_setfn(&rtc_timer, rtc_callback, NULL); ets_timer_setfn(&rtc_timer, rtc_callback, NULL);
ets_timer_arm_new(&rtc_timer, 1000, 1, 1); ets_timer_arm_new(&rtc_timer, 1000, 1, 1);
return 0; return 0;
} }
NODEMCU_MODULE(TMR, "tmr", tmr_map, luaopen_tmr); NODEMCU_MODULE(TMR, "tmr", tmr_map, luaopen_tmr);
...@@ -238,6 +238,19 @@ static int lu8g_getMode( lua_State *L ) ...@@ -238,6 +238,19 @@ static int lu8g_getMode( lua_State *L )
return 1; return 1;
} }
// Lua: u8g.setContrast( self, constrast )
static int lu8g_setContrast( lua_State *L )
{
lu8g_userdata_t *lud;
if ((lud = get_lud( L )) == NULL)
return 0;
u8g_SetContrast( LU8G, luaL_checkinteger( L, 2 ) );
return 0;
}
// Lua: u8g.setColorIndex( self, color ) // Lua: u8g.setColorIndex( self, color )
static int lu8g_setColorIndex( lua_State *L ) static int lu8g_setColorIndex( lua_State *L )
{ {
...@@ -1086,6 +1099,7 @@ static const LUA_REG_TYPE lu8g_display_map[] = { ...@@ -1086,6 +1099,7 @@ static const LUA_REG_TYPE lu8g_display_map[] = {
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g_getStrWidth ) }, { LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g_getStrWidth ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lu8g_getWidth ) }, { LSTRKEY( "getWidth" ), LFUNCVAL( lu8g_getWidth ) },
{ LSTRKEY( "nextPage" ), LFUNCVAL( lu8g_nextPage ) }, { LSTRKEY( "nextPage" ), LFUNCVAL( lu8g_nextPage ) },
{ LSTRKEY( "setContrast" ), LFUNCVAL( lu8g_setContrast ) },
{ LSTRKEY( "setColorIndex" ), LFUNCVAL( lu8g_setColorIndex ) }, { LSTRKEY( "setColorIndex" ), LFUNCVAL( lu8g_setColorIndex ) },
{ LSTRKEY( "setDefaultBackgroundColor" ), LFUNCVAL( lu8g_setDefaultBackgroundColor ) }, { LSTRKEY( "setDefaultBackgroundColor" ), LFUNCVAL( lu8g_setDefaultBackgroundColor ) },
{ LSTRKEY( "setDefaultForegroundColor" ), LFUNCVAL( lu8g_setDefaultForegroundColor ) }, { LSTRKEY( "setDefaultForegroundColor" ), LFUNCVAL( lu8g_setDefaultForegroundColor ) },
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "c_string.h" #include "c_string.h"
#include "rom.h" #include "rom.h"
static lua_State *gL = NULL;
static int uart_receive_rf = LUA_NOREF; static int uart_receive_rf = LUA_NOREF;
bool run_input = true; bool run_input = true;
bool uart_on_data_cb(const char *buf, size_t len){ bool uart_on_data_cb(const char *buf, size_t len){
...@@ -16,11 +15,12 @@ bool uart_on_data_cb(const char *buf, size_t len){ ...@@ -16,11 +15,12 @@ bool uart_on_data_cb(const char *buf, size_t len){
return false; return false;
if(uart_receive_rf == LUA_NOREF) if(uart_receive_rf == LUA_NOREF)
return false; return false;
if(!gL) lua_State *L = lua_getstate();
if(!L)
return false; return false;
lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_receive_rf); lua_rawgeti(L, LUA_REGISTRYINDEX, uart_receive_rf);
lua_pushlstring(gL, buf, len); lua_pushlstring(L, buf, len);
lua_call(gL, 1, 0); lua_call(L, 1, 0);
return !run_input; return !run_input;
} }
...@@ -75,7 +75,6 @@ static int uart_on( lua_State* L ) ...@@ -75,7 +75,6 @@ static int uart_on( lua_State* L )
} }
if(!lua_isnil(L, -1)){ if(!lua_isnil(L, -1)){
uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX); uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
gL = L;
if(run==0) if(run==0)
run_input = false; run_input = false;
} else { } else {
......
// Module for websockets
// Example usage:
// ws = websocket.createClient()
// ws:on("connection", function() ws:send('hi') end)
// ws:on("receive", function(_, data, opcode) print(data) end)
// ws:on("close", function(_, reasonCode) print('ws closed', reasonCode) end)
// ws:connect('ws://echo.websocket.org')
#include "lmem.h"
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "module.h"
#include "c_types.h"
#include "c_string.h"
#include "websocketclient.h"
#define METATABLE_WSCLIENT "websocket.client"
typedef struct ws_data {
int self_ref;
int onConnection;
int onReceive;
int onClose;
} ws_data;
static void websocketclient_onConnectionCallback(ws_info *ws) {
NODE_DBG("websocketclient_onConnectionCallback\n");
lua_State *L = lua_getstate();
if (ws == NULL || ws->reservedData == NULL) {
luaL_error(L, "Client websocket is nil.\n");
return;
}
ws_data *data = (ws_data *) ws->reservedData;
if (data->onConnection != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, data->onConnection); // load the callback function
lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument
lua_call(L, 1, 0);
}
}
static void websocketclient_onReceiveCallback(ws_info *ws, char *message, int opCode) {
NODE_DBG("websocketclient_onReceiveCallback\n");
lua_State *L = lua_getstate();
if (ws == NULL || ws->reservedData == NULL) {
luaL_error(L, "Client websocket is nil.\n");
return;
}
ws_data *data = (ws_data *) ws->reservedData;
if (data->onReceive != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, data->onReceive); // load the callback function
lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument
lua_pushstring(L, message); // #2 callback argument
lua_pushnumber(L, opCode); // #3 callback argument
lua_call(L, 3, 0);
}
}
static void websocketclient_onCloseCallback(ws_info *ws, int errorCode) {
NODE_DBG("websocketclient_onCloseCallback\n");
lua_State *L = lua_getstate();
if (ws == NULL || ws->reservedData == NULL) {
luaL_error(L, "Client websocket is nil.\n");
return;
}
ws_data *data = (ws_data *) ws->reservedData;
if (data->onClose != LUA_NOREF) {
lua_rawgeti(L, LUA_REGISTRYINDEX, data->onClose); // load the callback function
lua_rawgeti(L, LUA_REGISTRYINDEX, data->self_ref); // pass itself, #1 callback argument
lua_pushnumber(L, errorCode); // pass the error code, #2 callback argument
lua_call(L, 2, 0);
}
// free self-reference to allow gc (no futher callback will be called until next ws:connect())
lua_gc(L, LUA_GCSTOP, 0); // required to avoid freeing ws_data
luaL_unref(L, LUA_REGISTRYINDEX, data->self_ref);
data->self_ref = LUA_NOREF;
lua_gc(L, LUA_GCRESTART, 0);
}
static int websocket_createClient(lua_State *L) {
NODE_DBG("websocket_createClient\n");
// create user data
ws_data *data = (ws_data *) luaM_malloc(L, sizeof(ws_data));
data->onConnection = LUA_NOREF;
data->onReceive = LUA_NOREF;
data->onClose = LUA_NOREF;
data->self_ref = LUA_NOREF; // only set when ws:connect is called
ws_info *ws = (ws_info *) lua_newuserdata(L, sizeof(ws_info));
ws->connectionState = 0;
ws->onConnection = &websocketclient_onConnectionCallback;
ws->onReceive = &websocketclient_onReceiveCallback;
ws->onFailure = &websocketclient_onCloseCallback;
ws->reservedData = data;
// set its metatable
luaL_getmetatable(L, METATABLE_WSCLIENT);
lua_setmetatable(L, -2);
return 1;
}
static int websocketclient_on(lua_State *L) {
NODE_DBG("websocketclient_on\n");
ws_info *ws = (ws_info *) luaL_checkudata(L, 1, METATABLE_WSCLIENT);
luaL_argcheck(L, ws, 1, "Client websocket expected");
ws_data *data = (ws_data *) ws->reservedData;
int handle = luaL_checkoption(L, 2, NULL, (const char * const[]){ "connection", "receive", "close", NULL });
if (lua_type(L, 3) != LUA_TNIL && lua_type(L, 3) != LUA_TFUNCTION && lua_type(L, 3) != LUA_TLIGHTFUNCTION) {
return luaL_typerror(L, 3, "function or nil");
}
switch (handle) {
case 0:
NODE_DBG("connection\n");
luaL_unref(L, LUA_REGISTRYINDEX, data->onConnection);
data->onConnection = LUA_NOREF;
if (lua_type(L, 3) != LUA_TNIL) {
lua_pushvalue(L, 3); // copy argument (func) to the top of stack
data->onConnection = luaL_ref(L, LUA_REGISTRYINDEX);
}
break;
case 1:
NODE_DBG("receive\n");
luaL_unref(L, LUA_REGISTRYINDEX, data->onReceive);
data->onReceive = LUA_NOREF;
if (lua_type(L, 3) != LUA_TNIL) {
lua_pushvalue(L, 3); // copy argument (func) to the top of stack
data->onReceive = luaL_ref(L, LUA_REGISTRYINDEX);
}
break;
case 2:
NODE_DBG("close\n");
luaL_unref(L, LUA_REGISTRYINDEX, data->onClose);
data->onClose = LUA_NOREF;
if (lua_type(L, 3) != LUA_TNIL) {
lua_pushvalue(L, 3); // copy argument (func) to the top of stack
data->onClose = luaL_ref(L, LUA_REGISTRYINDEX);
}
break;
}
return 0;
}
static int websocketclient_connect(lua_State *L) {
NODE_DBG("websocketclient_connect is called.\n");
ws_info *ws = (ws_info *) luaL_checkudata(L, 1, METATABLE_WSCLIENT);
luaL_argcheck(L, ws, 1, "Client websocket expected");
ws_data *data = (ws_data *) ws->reservedData;
if (ws->connectionState != 0 && ws->connectionState != 4) {
return luaL_error(L, "Websocket already connecting or connected.\n");
}
ws->connectionState = 0;
lua_pushvalue(L, 1); // copy userdata to the top of stack to allow ref
data->self_ref = luaL_ref(L, LUA_REGISTRYINDEX);
const char *url = luaL_checkstring(L, 2);
ws_connect(ws, url);
return 0;
}
static int websocketclient_send(lua_State *L) {
NODE_DBG("websocketclient_send is called.\n");
ws_info *ws = (ws_info *) luaL_checkudata(L, 1, METATABLE_WSCLIENT);
luaL_argcheck(L, ws, 1, "Client websocket expected");
ws_data *data = (ws_data *) ws->reservedData;
if (ws->connectionState != 3) {
// should this be an onFailure callback instead?
return luaL_error(L, "Websocket isn't connected.\n");
}
int msgLength;
const char *msg = luaL_checklstring(L, 2, &msgLength);
int opCode = 1; // default: text message
if (lua_gettop(L) == 3) {
opCode = luaL_checkint(L, 3);
}
ws_send(ws, opCode, msg, (unsigned short) msgLength);
return 0;
}
static int websocketclient_close(lua_State *L) {
NODE_DBG("websocketclient_close.\n");
ws_info *ws = (ws_info *) luaL_checkudata(L, 1, METATABLE_WSCLIENT);
ws_close(ws);
return 0;
}
static int websocketclient_gc(lua_State *L) {
NODE_DBG("websocketclient_gc\n");
ws_info *ws = (ws_info *) luaL_checkudata(L, 1, METATABLE_WSCLIENT);
luaL_argcheck(L, ws, 1, "Client websocket expected");
ws_data *data = (ws_data *) ws->reservedData;
luaL_unref(L, LUA_REGISTRYINDEX, data->onConnection);
luaL_unref(L, LUA_REGISTRYINDEX, data->onReceive);
if (data->onClose != LUA_NOREF) {
if (ws->connectionState != 4) { // only call if connection open
lua_rawgeti(L, LUA_REGISTRYINDEX, data->onClose);
lua_pushnumber(L, -100);
lua_call(L, 1, 0);
}
luaL_unref(L, LUA_REGISTRYINDEX, data->onClose);
}
if (data->self_ref != LUA_NOREF) {
lua_gc(L, LUA_GCSTOP, 0); // required to avoid freeing ws_data
luaL_unref(L, LUA_REGISTRYINDEX, data->self_ref);
data->self_ref = LUA_NOREF;
lua_gc(L, LUA_GCRESTART, 0);
}
NODE_DBG("freeing lua data\n");
luaM_free(L, data);
NODE_DBG("done freeing lua data\n");
return 0;
}
static const LUA_REG_TYPE websocket_map[] =
{
{ LSTRKEY("createClient"), LFUNCVAL(websocket_createClient) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE websocketclient_map[] =
{
{ LSTRKEY("on"), LFUNCVAL(websocketclient_on) },
{ LSTRKEY("connect"), LFUNCVAL(websocketclient_connect) },
{ LSTRKEY("send"), LFUNCVAL(websocketclient_send) },
{ LSTRKEY("close"), LFUNCVAL(websocketclient_close) },
{ LSTRKEY("__gc" ), LFUNCVAL(websocketclient_gc) },
{ LSTRKEY("__index"), LROVAL(websocketclient_map) },
{ LNILKEY, LNILVAL }
};
int loadWebsocketModule(lua_State *L) {
luaL_rometatable(L, METATABLE_WSCLIENT, (void *) websocketclient_map);
return 0;
}
NODEMCU_MODULE(WEBSOCKET, "websocket", websocket_map, loadWebsocketModule);
...@@ -372,6 +372,26 @@ static int wifi_sleep(lua_State* L) ...@@ -372,6 +372,26 @@ static int wifi_sleep(lua_State* L)
return 2; return 2;
} }
//wifi.nullmodesleep()
static int wifi_null_mode_auto_sleep(lua_State* L)
{
if (!lua_isnone(L, 1))
{
bool auto_sleep_setting=lua_toboolean(L, 1);
if (auto_sleep_setting!=(bool) get_fpm_auto_sleep_flag())
{
wifi_fpm_auto_sleep_set_in_null_mode((uint8)auto_sleep_setting);
//if esp is already in NULL_MODE, auto sleep setting won't take effect until next wifi_set_opmode(NULL_MODE) call.
if(wifi_get_opmode()==NULL_MODE)
{
wifi_set_opmode_current(NULL_MODE);
}
}
}
lua_pushboolean(L, (bool) get_fpm_auto_sleep_flag());
return 1;
}
// Lua: mac = wifi.xx.getmac() // Lua: mac = wifi.xx.getmac()
static int wifi_getmac( lua_State* L, uint8_t mode ) static int wifi_getmac( lua_State* L, uint8_t mode )
{ {
...@@ -1268,6 +1288,7 @@ static const LUA_REG_TYPE wifi_map[] = { ...@@ -1268,6 +1288,7 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) }, { LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) },
{ LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) }, { LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( wifi_sleep ) }, { LSTRKEY( "sleep" ), LFUNCVAL( wifi_sleep ) },
{ LSTRKEY( "nullmodesleep" ), LFUNCVAL( wifi_null_mode_auto_sleep ) },
#ifdef WIFI_SMART_ENABLE #ifdef WIFI_SMART_ENABLE
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) }, { LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
{ LSTRKEY( "stopsmart" ), LFUNCVAL( wifi_exit_smart ) }, { LSTRKEY( "stopsmart" ), LFUNCVAL( wifi_exit_smart ) },
...@@ -1349,6 +1370,12 @@ void wifi_change_default_host_name(void) ...@@ -1349,6 +1370,12 @@ void wifi_change_default_host_name(void)
int luaopen_wifi( lua_State *L ) int luaopen_wifi( lua_State *L )
{ {
wifi_fpm_auto_sleep_set_in_null_mode(1);
//if esp is already in NULL_MODE, auto sleep setting won't take effect until next wifi_set_opmode(NULL_MODE) call.
if(wifi_get_opmode()==NULL_MODE)
{
wifi_set_opmode_current(NULL_MODE);
}
#if defined(WIFI_SDK_EVENT_MONITOR_ENABLE) #if defined(WIFI_SDK_EVENT_MONITOR_ENABLE)
wifi_eventmon_init(); wifi_eventmon_init();
#endif #endif
......
#include "flash_fs.h"
#include "c_string.h"
#include "spiffs.h"
int fs_mode2flag(const char *mode){
if(c_strlen(mode)==1){
if(c_strcmp(mode,"w")==0)
return FS_WRONLY|FS_CREAT|FS_TRUNC;
else if(c_strcmp(mode, "r")==0)
return FS_RDONLY;
else if(c_strcmp(mode, "a")==0)
return FS_WRONLY|FS_CREAT|FS_APPEND;
else
return FS_RDONLY;
} else if (c_strlen(mode)==2){
if(c_strcmp(mode,"r+")==0)
return FS_RDWR;
else if(c_strcmp(mode, "w+")==0)
return FS_RDWR|FS_CREAT|FS_TRUNC;
else if(c_strcmp(mode, "a+")==0)
return FS_RDWR|FS_CREAT|FS_APPEND;
else
return FS_RDONLY;
} else {
return FS_RDONLY;
}
}
#ifndef __FLASH_FS_H__
#define __FLASH_FS_H__
#include "user_config.h"
#if defined( BUILD_SPIFFS )
#include "myspiffs.h"
#define FS_OPEN_OK 1
#define FS_RDONLY SPIFFS_RDONLY
#define FS_WRONLY SPIFFS_WRONLY
#define FS_RDWR SPIFFS_RDWR
#define FS_APPEND SPIFFS_APPEND
#define FS_TRUNC SPIFFS_TRUNC
#define FS_CREAT SPIFFS_CREAT
#define FS_EXCL SPIFFS_EXCL
#define FS_SEEK_SET SPIFFS_SEEK_SET
#define FS_SEEK_CUR SPIFFS_SEEK_CUR
#define FS_SEEK_END SPIFFS_SEEK_END
#define fs_open myspiffs_open
#define fs_close myspiffs_close
#define fs_write myspiffs_write
#define fs_read myspiffs_read
#define fs_seek myspiffs_lseek
#define fs_eof myspiffs_eof
#define fs_getc myspiffs_getc
#define fs_ungetc myspiffs_ungetc
#define fs_flush myspiffs_flush
#define fs_error myspiffs_error
#define fs_clearerr myspiffs_clearerr
#define fs_tell myspiffs_tell
#define fs_format myspiffs_format
#define fs_check myspiffs_check
#define fs_rename myspiffs_rename
#define fs_size myspiffs_size
#define fs_mount myspiffs_mount
#define fs_unmount myspiffs_unmount
#define FS_NAME_MAX_LENGTH SPIFFS_OBJ_NAME_LEN
#endif
int fs_mode2flag(const char *mode);
#endif // #ifndef __FLASH_FS_H__
...@@ -671,7 +671,7 @@ int platform_i2c_recv_byte( unsigned id, int ack ){ ...@@ -671,7 +671,7 @@ int platform_i2c_recv_byte( unsigned id, int ack ){
// ***************************************************************************** // *****************************************************************************
// SPI platform interface // SPI platform interface
uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div) uint32_t platform_spi_setup( uint8_t id, int mode, unsigned cpol, unsigned cpha, uint32_t clock_div )
{ {
spi_master_init( id, cpol, cpha, clock_div ); spi_master_init( id, cpol, cpha, clock_div );
return 1; return 1;
...@@ -696,6 +696,49 @@ spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type ...@@ -696,6 +696,49 @@ spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type
return spi_mast_get_miso( id, 0, bitlen ); return spi_mast_get_miso( id, 0, bitlen );
} }
int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data )
{
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0) {
size_t chunk_len = len > 64 ? 64 : len;
spi_mast_blkset( id, chunk_len * 8, data );
spi_mast_transaction( id, 0, 0, 0, 0, chunk_len * 8, 0, 0 );
data = &(data[chunk_len]);
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data )
{
uint8_t mosi_idle[64];
os_memset( (void *)mosi_idle, 0xff, len > 64 ? 64 : len );
spi_mast_byte_order( id, SPI_ORDER_LSB );
while (len > 0 ) {
size_t chunk_len = len > 64 ? 64 : len;
spi_mast_blkset( id, chunk_len * 8, mosi_idle );
spi_mast_transaction( id, 0, 0, 0, 0, chunk_len * 8, 0, -1 );
spi_mast_blkget( id, chunk_len * 8, data );
data = &(data[chunk_len]);
len -= chunk_len;
}
spi_mast_byte_order( id, SPI_ORDER_MSB );
return PLATFORM_OK;
}
int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data ) int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data )
{ {
if (offset + bitlen > 512) if (offset + bitlen > 512)
......
...@@ -110,6 +110,8 @@ int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data ); ...@@ -110,6 +110,8 @@ int platform_spi_send( uint8_t id, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data ); spi_data_type platform_spi_send_recv( uint8_t id, uint8_t bitlen, spi_data_type data );
void platform_spi_select( unsigned id, int is_select ); void platform_spi_select( unsigned id, int is_select );
int platform_spi_blkwrite( uint8_t id, size_t len, const uint8_t *data );
int platform_spi_blkread( uint8_t id, size_t len, uint8_t *data );
int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data ); int platform_spi_set_mosi( uint8_t id, uint16_t offset, uint8_t bitlen, spi_data_type data );
spi_data_type platform_spi_get_miso( uint8_t id, uint16_t offset, uint8_t bitlen ); spi_data_type platform_spi_get_miso( uint8_t id, uint16_t offset, uint8_t bitlen );
int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data, int platform_spi_transaction( uint8_t id, uint8_t cmd_bitlen, spi_data_type cmd_data,
......
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