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;
typedef struct lcoap_userdata
{
lua_State *L;
struct espconn *pesp_conn;
int self_ref;
}lcoap_userdata;
......@@ -103,7 +102,6 @@ static int coap_create( lua_State* L, const char* mt )
pesp_conn->state = ESPCONN_NONE;
NODE_DBG("UDP server/client is set.\n");
cud->L = L;
pesp_conn->reverse = cud;
NODE_DBG("coap_create is called.\n");
......@@ -129,7 +127,6 @@ static int coap_delete( lua_State* L, const char* mt )
cud->self_ref = LUA_NOREF;
}
cud->L = NULL;
if(cud->pesp_conn)
{
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 )
return luaL_error(L, "not enough memory");
h->next = NULL;
h->name = NULL;
h->L = NULL;
}
h->L = L;
h->name = name;
h->content_type = content_type;
......
......@@ -6,14 +6,21 @@
#include "platform.h"
#include "c_types.h"
#include "c_stdlib.h"
#include "flash_fs.h"
#include "vfs.h"
#include "../crypto/digests.h"
#include "../crypto/mech.h"
#include "lmem.h"
#include "user_interface.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)
*
......@@ -150,11 +157,6 @@ static int crypto_lhash (lua_State *L)
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:
* sha = crypto.new_hash("MD5")
* sha.update("Data")
......@@ -162,19 +164,30 @@ typedef struct digest_user_datum_t {
* strdigest = crypto.toHex(sha.finalize())
*/
/* crypto.new_hash("MECHTYPE") */
static int crypto_new_hash (lua_State *L)
#define WANT_HASH 0
#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));
if (!mi)
return bad_mech (L);
void *ctx = os_malloc (mi->ctx_size);
if (ctx==NULL)
return bad_mem (L);
size_t len = 0;
const char *key = 0;
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);
if (what == WANT_HMAC)
crypto_hmac_begin (ctx, mi, key, len, k_opad);
// create a userdataum with specific metatable
digest_user_datum_t *dudat = (digest_user_datum_t *)lua_newuserdata(L, sizeof(digest_user_datum_t));
luaL_getmetatable(L, "crypto.hash");
......@@ -183,10 +196,24 @@ static int crypto_new_hash (lua_State *L)
// Set pointers to the mechanics and CTX
dudat->mech_info = mi;
dudat->ctx = ctx;
dudat->k_opad = k_opad;
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:
1 - userdata "this"
2 - new string to add to the hash state */
......@@ -197,7 +224,6 @@ static int crypto_hash_update (lua_State *L)
size_t sl;
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;
......@@ -217,11 +243,13 @@ static int crypto_hash_finalize (lua_State *L)
size_t sl;
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;
uint8_t digest[mi->digest_size]; // Allocate as local
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));
......@@ -235,14 +263,21 @@ static int crypto_hash_gcdelete (lua_State *L)
digest_user_datum_t *dudat;
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;
}
static sint32_t vfs_read_wrap (int fd, void *ptr, size_t len)
{
return vfs_read (fd, ptr, len);
}
/* rawdigest = crypto.hash("MD5", filename)
* strdigest = crypto.toHex(rawdigest)
*/
......@@ -254,17 +289,17 @@ static int crypto_flhash (lua_State *L)
const char *filename = luaL_checkstring (L, 2);
// Open the file
int file_fd = fs_open (filename, FS_RDONLY);
if(file_fd < FS_OPEN_OK) {
int file_fd = vfs_open (filename, "r");
if(!file_fd) {
return bad_file(L);
}
// Compute hash
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
fs_close(file_fd);
vfs_close(file_fd);
if (returncode == ENOMEM)
return bad_mem (L);
......@@ -381,6 +416,7 @@ static const LUA_REG_TYPE crypto_map[] = {
{ LSTRKEY( "fhash" ), LFUNCVAL( crypto_flhash ) },
{ LSTRKEY( "new_hash" ), LFUNCVAL( crypto_new_hash ) },
{ LSTRKEY( "hmac" ), LFUNCVAL( crypto_lhmac ) },
{ LSTRKEY( "new_hmac" ), LFUNCVAL( crypto_new_hmac ) },
{ LSTRKEY( "encrypt" ), LFUNCVAL( lcrypto_encrypt ) },
{ LSTRKEY( "decrypt" ), LFUNCVAL( lcrypto_decrypt ) },
{ LNILKEY, LNILVAL }
......
......@@ -45,7 +45,7 @@
#include "espconn.h"
#include "lwip/tcp.h"
#include "lwip/pbuf.h"
#include "flash_fs.h"
#include "vfs.h"
#include "task/task.h"
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
......@@ -485,20 +485,20 @@ static int enduser_setup_http_load_payload(void)
{
ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload");
int err = (FS_OPEN_OK -1);
int err2 = (FS_OPEN_OK -1);
int err = VFS_RES_ERR;
int err2 = VFS_RES_ERR;
int file_len = 0;
int f = fs_open(http_html_filename, fs_mode2flag("r"));
if (f >= FS_OPEN_OK) {
err = fs_seek(f, 0, FS_SEEK_END);
file_len = (int) fs_tell(f);
err2 = fs_seek(f, 0, FS_SEEK_SET);
int f = vfs_open(http_html_filename, "r");
if (f) {
err = vfs_lseek(f, 0, VFS_SEEK_END);
file_len = (int) vfs_tell(f);
err2 = vfs_lseek(f, 0, VFS_SEEK_SET);
}
const char cl_hdr[] = "Content-length:%5d\r\n\r\n";
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.");
......@@ -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));
offset += LITLEN(http_header_200);
offset += c_sprintf(state->http_payload_data + offset, cl_hdr, file_len);
fs_read(f, &(state->http_payload_data[offset]), file_len);
fs_close(f);
vfs_read(f, &(state->http_payload_data[offset]), file_len);
vfs_close(f);
return 0;
}
......
......@@ -5,42 +5,95 @@
#include "platform.h"
#include "c_types.h"
#include "flash_fs.h"
#include "vfs.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;
if((FS_OPEN_OK - 1)!=file_fd){
fs_close(file_fd);
file_fd = FS_OPEN_OK - 1;
}
int idx = lua_gettop( L );
// extract items from table
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 );
luaL_argcheck(L, len < FS_NAME_MAX_LENGTH && c_strlen(fname) == len, 1, "filename invalid");
static sint32_t file_rtc_cb( vfs_time *tm )
{
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){
file_fd = FS_OPEN_OK - 1;
lua_pushnil(L);
if (lua_type( L, lua_gettop( L ) ) == LUA_TTABLE) {
table2tm( L, tm );
res = VFS_RES_OK;
}
// pop item returned by callback
lua_pop( L, 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 {
lua_pushboolean(L, 1);
rtc_cb_ref = LUA_NOREF;
vfs_register_rtc_cb(NULL);
}
return 1;
break;
default:
break;
}
return 0;
}
// Lua: close()
static int file_close( lua_State* L )
{
if((FS_OPEN_OK - 1)!=file_fd){
fs_close(file_fd);
file_fd = FS_OPEN_OK - 1;
if(file_fd){
vfs_close(file_fd);
file_fd = 0;
}
return 0;
}
......@@ -50,7 +103,7 @@ static int file_format( lua_State* L )
{
size_t len;
file_close(L);
if( !fs_format() )
if( !vfs_format() )
{
NODE_ERR( "\n*** ERROR ***: unable to format. FS might be compromised.\n" );
NODE_ERR( "It is advised to re-flash the NodeMCU image.\n" );
......@@ -62,41 +115,74 @@ static int file_format( lua_State* L )
return 0;
}
#if defined(BUILD_SPIFFS)
static int file_fscfg (lua_State *L)
{
uint32_t phys_addr, phys_size;
extern spiffs fs;
vfs_fscfg("/FLASH", &phys_addr, &phys_size);
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()
static int file_list( lua_State* L )
{
spiffs_DIR d;
struct spiffs_dirent e;
struct spiffs_dirent *pe = &e;
vfs_dir *dir;
vfs_item *item;
if (dir = vfs_opendir("")) {
lua_newtable( L );
SPIFFS_opendir(&fs, "/", &d);
while ((pe = SPIFFS_readdir(&d, pe))) {
// NODE_ERR(" %s size:%i\n", pe->name, pe->size);
lua_pushinteger(L, pe->size);
lua_setfield( L, -2, pe->name );
while (item = vfs_readdir(dir)) {
lua_pushinteger(L, vfs_item_size(item));
lua_setfield(L, -2, vfs_item_name(item));
vfs_closeitem(item);
}
SPIFFS_closedir(&d);
vfs_closedir(dir);
return 1;
}
return 0;
}
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};
if((FS_OPEN_OK - 1)==file_fd)
if(!file_fd)
return luaL_error(L, "open a file first");
int op = luaL_checkoption(L, 1, "cur", modenames);
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)
lua_pushnil(L); /* error */
else
lua_pushinteger(L, fs_tell(file_fd));
lua_pushinteger(L, vfs_tell(file_fd));
return 1;
}
......@@ -105,12 +191,14 @@ static int file_exists( lua_State* L )
{
size_t 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");
vfs_item *stat = vfs_stat((char *)fname);
spiffs_stat stat;
int rc = SPIFFS_stat(&fs, (char *)fname, &stat);
lua_pushboolean(L, stat ? 1 : 0);
lua_pushboolean(L, (rc == SPIFFS_OK ? 1 : 0));
if (stat) vfs_closeitem(stat);
return 1;
}
......@@ -120,49 +208,43 @@ static int file_remove( lua_State* L )
{
size_t 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);
SPIFFS_remove(&fs, (char *)fname);
vfs_remove((char *)fname);
return 0;
}
// Lua: flush()
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");
if(fs_flush(file_fd) == 0)
if(vfs_flush(file_fd) == 0)
lua_pushboolean(L, 1);
else
lua_pushnil(L);
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")
static int file_rename( lua_State* L )
{
size_t len;
if((FS_OPEN_OK - 1)!=file_fd){
fs_close(file_fd);
file_fd = FS_OPEN_OK - 1;
if(file_fd){
vfs_close(file_fd);
file_fd = 0;
}
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 );
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);
} else {
lua_pushboolean(L, 0);
......@@ -170,26 +252,6 @@ static int file_rename( lua_State* L )
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()
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;
luaL_Buffer b;
if((FS_OPEN_OK - 1)==file_fd)
if(!file_fd)
return luaL_error(L, "open a file first");
luaL_buffinit(L, &b);
char *p = luaL_prepbuffer(&b);
int i;
n = fs_read(file_fd, p, n);
n = vfs_read(file_fd, p, n);
for (i = 0; i < n; ++i)
if (p[i] == 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 */
}
fs_seek(file_fd, -(n - i), SEEK_CUR);
vfs_lseek(file_fd, -(n - i), VFS_SEEK_CUR);
luaL_addsize(&b, i);
luaL_pushresult(&b); /* close buffer */
return 1; /* read at least an `eol' */
......@@ -262,11 +324,11 @@ static int file_readline( lua_State* L )
// Lua: write("string")
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");
size_t l, rl;
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)
lua_pushboolean(L, 1);
else
......@@ -277,13 +339,13 @@ static int file_write( lua_State* L )
// Lua: writeline("string")
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");
size_t l, rl;
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){
rl = fs_write(file_fd, "\n", 1);
rl = vfs_write(file_fd, "\n", 1);
if(rl==1)
lua_pushboolean(L, 1);
else
......@@ -295,13 +357,79 @@ static int file_writeline( lua_State* L )
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);
lua_pushinteger (L, fs.cfg.phys_size);
return 2;
u32_t total, used;
if (vfs_fsinfo("", &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;
}
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
static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "list" ), LFUNCVAL( file_list ) },
......@@ -311,17 +439,27 @@ static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "writeline" ), LFUNCVAL( file_writeline ) },
{ LSTRKEY( "read" ), LFUNCVAL( file_read ) },
{ LSTRKEY( "readline" ), LFUNCVAL( file_readline ) },
#ifdef BUILD_SPIFFS
{ LSTRKEY( "format" ), LFUNCVAL( file_format ) },
#if defined(BUILD_SPIFFS)
{ LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
#endif
{ LSTRKEY( "remove" ), LFUNCVAL( file_remove ) },
{ LSTRKEY( "seek" ), LFUNCVAL( file_seek ) },
{ LSTRKEY( "flush" ), LFUNCVAL( file_flush ) },
{ LSTRKEY( "rename" ), LFUNCVAL( file_rename ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "fscfg" ), LFUNCVAL( file_fscfg ) },
{ 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
{ 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 )
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;
}
......
......@@ -125,6 +125,7 @@ static void mqtt_socket_disconnected(void *arg) // tcp only
mud->pesp_conn = NULL;
}
mud->connected = false;
luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref);
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)
pesp_conn->proto.tcp->local_port = espconn_port();
socket_connect(pesp_conn);
} else {
#ifdef CLIENT_SSL_ENABLE
if (mud->secure) {
espconn_secure_disconnect(pesp_conn);
} else
#endif
{
espconn_disconnect(pesp_conn);
}
mqtt_socket_disconnected(arg);
}
NODE_DBG("leave mqtt_socket_reconnected.\n");
......@@ -804,6 +813,9 @@ static int mqtt_delete( lua_State* L )
c_free(mud->pesp_conn);
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()
if(mud->connect_info.will_topic){
......@@ -873,7 +885,6 @@ static sint8 socket_connect(struct espconn *pesp_conn)
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
{
espconn_secure_set_size(ESPCONN_CLIENT, 5120); /* set SSL buffer size */
espconn_status = espconn_secure_connect(pesp_conn);
}
else
......@@ -884,7 +895,7 @@ static sint8 socket_connect(struct espconn *pesp_conn)
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;
}
......@@ -971,21 +982,16 @@ static int mqtt_socket_connect( lua_State* L )
return luaL_error(L, "already connected");
}
if(mud->pesp_conn){ //TODO: should I free tcp struct directly or ask user to call close()???
mud->pesp_conn->reverse = NULL;
if(mud->pesp_conn->proto.tcp)
c_free(mud->pesp_conn->proto.tcp);
mud->pesp_conn->proto.tcp = NULL;
c_free(mud->pesp_conn);
mud->pesp_conn = NULL;
struct espconn *pesp_conn = mud->pesp_conn;
if(!pesp_conn) {
pesp_conn = mud->pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn));
} else {
espconn_delete(pesp_conn);
}
struct espconn *pesp_conn = NULL;
pesp_conn = mud->pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn));
if(!pesp_conn)
return luaL_error(L, "not enough memory");
pesp_conn->proto.udp = NULL;
if (!pesp_conn->proto.tcp)
pesp_conn->proto.tcp = (esp_tcp *)c_zalloc(sizeof(esp_tcp));
if(!pesp_conn->proto.tcp){
c_free(pesp_conn);
......@@ -1021,6 +1027,7 @@ static int mqtt_socket_connect( lua_State* L )
NODE_DBG("TCP port is set: %d.\n", port);
}
pesp_conn->proto.tcp->remote_port = port;
if (pesp_conn->proto.tcp->local_port == 0)
pesp_conn->proto.tcp->local_port = espconn_port();
mud->mqtt_state.port = port;
......@@ -1121,31 +1128,33 @@ static int mqtt_socket_close( lua_State* L )
return 1;
}
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]);
sint8 espconn_status;
#ifdef CLIENT_SSL_ENABLE
if(mud->secure)
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.
#ifdef CLIENT_SSL_ENABLE
if(mud->secure){
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
{
espconn_status = espconn_send(mud->pesp_conn, temp_msg->data, temp_msg->length);
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");
if (espconn_status == ESPCONN_OK) {
......
......@@ -34,7 +34,6 @@ static int expose_array(lua_State* L, char *array, unsigned short len);
#define MAX_SOCKET 5
static int socket_num = 0;
static int socket[MAX_SOCKET];
static lua_State *gL = NULL;
static int tcpserver_cb_connect_ref = LUA_NOREF; // for tcp server connected callback
static uint16_t tcp_server_timeover = 30;
......@@ -65,8 +64,7 @@ static void net_server_disconnected(void *arg) // for tcp server only
lnet_userdata *nud = (lnet_userdata *)pesp_conn->reverse;
if(nud == NULL)
return;
if(gL == NULL)
return;
lua_State *L = lua_getstate();
#if 0
char temp[20] = {0};
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
#endif
if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF)
{
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(gL, 1, 0);
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(L, 1, 0);
}
int i;
lua_gc(gL, LUA_GCSTOP, 0);
lua_gc(L, LUA_GCSTOP, 0);
for(i=0;i<MAX_SOCKET;i++){
if( (LUA_NOREF!=socket[i]) && (socket[i] == nud->self_ref) ){
// found the saved client
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->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_num--;
break;
}
}
lua_gc(gL, LUA_GCRESTART, 0);
lua_gc(L, LUA_GCRESTART, 0);
}
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;
if(nud == NULL)
return;
lua_State *L = lua_getstate();
if(nud->cb_disconnect_ref != LUA_NOREF && nud->self_ref != LUA_NOREF)
{
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(gL, 1, 0);
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_disconnect_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(L, 1, 0);
}
if(pesp_conn->proto.tcp)
......@@ -121,12 +120,12 @@ static void net_socket_disconnected(void *arg) // tcp only
if(nud->pesp_conn)
c_free(nud->pesp_conn);
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){
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
}
lua_gc(gL, LUA_GCRESTART, 0);
lua_gc(L, LUA_GCRESTART, 0);
}
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)
return;
if(nud->self_ref == LUA_NOREF)
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_receive_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua
// expose_array(gL, pdata, len);
lua_State *L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_receive_ref);
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;
// NODE_DBG(pdata);
// NODE_DBG("\n");
lua_pushlstring(gL, pdata, len);
// lua_pushinteger(gL, len);
lua_call(gL, 2, 0);
lua_pushlstring(L, pdata, len);
// lua_pushinteger(L, len);
lua_call(L, 2, 0);
}
static void net_socket_sent(void *arg)
......@@ -178,9 +178,10 @@ static void net_socket_sent(void *arg)
return;
if(nud->self_ref == LUA_NOREF)
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_send_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(server) to callback func in lua
lua_call(gL, 1, 0);
lua_State *L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_send_ref);
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)
......@@ -205,34 +206,16 @@ static void net_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
NODE_DBG("self_ref null.\n");
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_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(conn) to callback func in lua
lua_pushstring(gL, ip_str); // the ip para
*/
lua_State *L = lua_getstate();
// "enhanced"
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
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
if(ipaddr == NULL)
{
NODE_DBG( "DNS Fail!\n" );
lua_pushnil(gL);
lua_pushnil(L);
}else{
// ipaddr->addr is a uint32_t ip
char ip_str[20];
......@@ -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)));
}
lua_pushstring(gL, ip_str); // the ip para
lua_pushstring(L, ip_str); // the ip para
}
// "enhanced" end
lua_call(gL, 2, 0);
lua_call(L, 2, 0);
end:
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) ){
lua_gc(gL, LUA_GCSTOP, 0);
lua_gc(L, LUA_GCSTOP, 0);
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
}
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
if(tcpserver_cb_connect_ref == LUA_NOREF)
return;
if(!gL)
return;
lua_State *L = lua_getstate();
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
skt = (lnet_userdata *)lua_newuserdata(gL, sizeof(lnet_userdata));
skt = (lnet_userdata *)lua_newuserdata(L, sizeof(lnet_userdata));
if(!skt){
NODE_ERR("can't newudata\n");
lua_pop(gL, 1);
lua_pop(L, 1);
return;
}
// set its metatable
luaL_getmetatable(gL, "net.socket");
lua_setmetatable(gL, -2);
luaL_getmetatable(L, "net.socket");
lua_setmetatable(L, -2);
// pre-initialize it, in case of errors
skt->self_ref = LUA_NOREF;
lua_pushvalue(gL, -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
lua_pushvalue(L, -1); // copy the top of stack
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_num++;
skt->cb_connect_ref = LUA_NOREF; // this socket already connected
......@@ -337,7 +319,7 @@ static void net_server_connected(void *arg) // for tcp only
espconn_regist_reconcb(pesp_conn, net_server_reconnected);
// 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)
......@@ -358,9 +340,10 @@ static void net_socket_connected(void *arg)
return;
if(nud->self_ref == LUA_NOREF)
return;
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->cb_connect_ref);
lua_rawgeti(gL, LUA_REGISTRYINDEX, nud->self_ref); // pass the userdata(client) to callback func in lua
lua_call(gL, 1, 0);
lua_State *L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, nud->cb_connect_ref);
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))
......@@ -492,8 +475,6 @@ static int net_create( lua_State* L, const char* mt )
pUdpServer = pesp_conn;
}
gL = L; // global L for net module.
// if call back function is specified, call it with para userdata
// luaL_checkanyfunction(L, 2);
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 )
luaL_unref(L, LUA_REGISTRYINDEX, nud->cb_dns_found_ref);
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){
luaL_unref(L, LUA_REGISTRYINDEX, nud->self_ref);
nud->self_ref = LUA_NOREF;
}
lua_gc(gL, LUA_GCRESTART, 0);
lua_gc(L, LUA_GCRESTART, 0);
return 0;
}
......@@ -596,7 +577,6 @@ static void socket_connect(struct espconn *pesp_conn)
{
#ifdef CLIENT_SSL_ENABLE
if(nud->secure){
espconn_secure_set_size(ESPCONN_CLIENT, 5120); /* set SSL buffer size */
espconn_secure_connect(pesp_conn);
}
else
......@@ -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;
if(nud == NULL)
return;
if(gL == NULL)
return;
lua_State *L = lua_getstate();
if(ipaddr == NULL)
{
dns_reconn_count++;
if( dns_reconn_count >= 5 ){
NODE_ERR( "DNS Fail!\n" );
lua_gc(gL, LUA_GCSTOP, 0);
lua_gc(L, LUA_GCSTOP, 0);
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
}
lua_gc(gL, LUA_GCRESTART, 0);
lua_gc(L, LUA_GCRESTART, 0);
return;
}
NODE_ERR( "DNS retry %d!\n", dns_reconn_count );
......@@ -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_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(gL, LUA_REGISTRYINDEX, rfunc); // load the callback function back to the stack
lua_rawgeti(L, LUA_REGISTRYINDEX, rdom); // load domain 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, rfunc); //free reference
......
......@@ -23,7 +23,7 @@
#include "driver/uart.h"
#include "user_interface.h"
#include "flash_api.h"
#include "flash_fs.h"
#include "vfs.h"
#include "user_version.h"
#include "rom.h"
#include "task/task.h"
......@@ -146,160 +146,6 @@ static int node_heap( lua_State* L )
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 bool user_process_input(bool force);
// Lua: input("string")
......@@ -333,7 +179,7 @@ void output_redirect(const char *str) {
// return;
// }
if (output_redir_ref == LUA_NOREF || !L) {
if (output_redir_ref == LUA_NOREF) {
uart0_sendStr(str);
return;
}
......@@ -380,11 +226,11 @@ static int writer(lua_State* L, const void* p, size_t size, void* u)
{
UNUSED(L);
int file_fd = *( (int *)u );
if ((FS_OPEN_OK - 1) == file_fd)
if (!file_fd)
return 1;
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;
NODE_DBG("write fd:%d,size:%d\n", file_fd, size);
return 0;
......@@ -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 )
{
Proto* f;
int file_fd = FS_OPEN_OK - 1;
int file_fd = 0;
size_t len;
const char *fname = luaL_checklstring( L, 1, &len );
if ( len >= FS_NAME_MAX_LENGTH )
return luaL_error(L, "filename too long");
const char *basename = vfs_basename( fname );
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);
// 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");
}
output[c_strlen(output) - 2] = 'c';
output[c_strlen(output) - 1] = '\0';
NODE_DBG(output);
NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) {
luaM_free( L, output );
return luaL_error(L, lua_tostring(L, -1));
}
......@@ -419,9 +268,10 @@ static int node_compile( lua_State* L )
int stripping = 1; /* strip debug information? */
file_fd = fs_open(output, fs_mode2flag("w+"));
if (file_fd < FS_OPEN_OK)
file_fd = vfs_open(output, "w+");
if (!file_fd)
{
luaM_free( L, output );
return luaL_error(L, "cannot open/write to file");
}
......@@ -429,12 +279,13 @@ static int node_compile( lua_State* L )
int result = luaU_dump(L, f, writer, &file_fd, stripping);
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
result = 1;
}
fs_close(file_fd);
file_fd = FS_OPEN_OK - 1;
vfs_close(file_fd);
file_fd = 0;
luaM_free( L, output );
if (result == LUA_ERR_CC_INTOVERFLOW) {
return luaL_error(L, "value too big or small for target integer type");
......@@ -643,10 +494,6 @@ static const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
{ 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( "output" ), LFUNCVAL( node_output ) },
// 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
(void)port;
sntp_dbg("sntp: on_recv\n");
lua_State *L = arg;
lua_State *L = lua_getstate();
if (!state || state->pcb != pcb)
{
......
......@@ -309,7 +309,7 @@ static int b_unpack (lua_State *L) {
size_t size = optsize(L, opt, &fmt);
pos += gettoalign(pos, &h, opt, size);
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) {
case 'b': case 'B': case 'h': case 'H':
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);
typedef struct{
os_timer_t os;
sint32_t lua_ref;
sint32_t lua_ref, self_ref;
uint32_t interval;
uint8_t mode;
}timer_struct_t;
......@@ -95,11 +95,17 @@ static timer_struct_t alarm_timers[NUM_TMR];
static os_timer_t rtc_timer;
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();
if(tmr->lua_ref == LUA_NOREF)
return;
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(tmr->mode == TIMER_MODE_SINGLE){
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
......@@ -108,7 +114,11 @@ static void alarm_timer_common(void* arg){
}else if(tmr->mode == TIMER_MODE_SEMI){
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 )
......@@ -135,20 +145,32 @@ static int tmr_now(lua_State* L){
return 1;
}
// Lua: tmr.register( id, interval, mode, function )
static int tmr_register(lua_State* L){
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){
timer_t tmr = tmr_get(L, 1);
uint32_t interval = luaL_checkinteger(L, 2);
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, (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");
//get the lua function reference
lua_pushvalue(L, 4);
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)
ets_timer_disarm(&tmr->os);
//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){
tmr->lua_ref = ref;
tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval;
ets_timer_setfn(&tmr->os, alarm_timer_common, (void*)id);
ets_timer_setfn(&tmr->os, alarm_timer_common, tmr);
return 0;
}
// Lua: tmr.start( id )
// Lua: tmr.start( id / ref )
static int tmr_start(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
timer_t tmr = tmr_get(L, 1);
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
if(!(tmr->mode&TIMER_IDLE_FLAG)){
lua_pushboolean(L, 0);
......@@ -177,17 +203,21 @@ static int tmr_start(lua_State* L){
return 1;
}
// Lua: tmr.alarm( id, interval, repeat, function )
// Lua: tmr.alarm( id / ref, interval, repeat, function )
static int tmr_alarm(lua_State* L){
tmr_register(L);
return tmr_start(L);
}
// Lua: tmr.stop( id )
// Lua: tmr.stop( id / ref )
static int tmr_stop(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
timer_t tmr = tmr_get(L, 1);
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)
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){
tmr->mode |= TIMER_IDLE_FLAG;
......@@ -199,11 +229,15 @@ static int tmr_stop(lua_State* L){
return 1;
}
// Lua: tmr.unregister( id )
// Lua: tmr.unregister( id / ref )
static int tmr_unregister(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
timer_t tmr = tmr_get(L, 1);
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)
ets_timer_disarm(&tmr->os);
if(tmr->lua_ref != LUA_NOREF)
......@@ -213,11 +247,10 @@ static int tmr_unregister(lua_State* L){
return 0;
}
// Lua: tmr.interval( id, interval )
// Lua: tmr.interval( id / ref, interval )
static int tmr_interval(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
timer_t tmr = tmr_get(L, 1);
uint32_t interval = luaL_checkinteger(L, 2);
luaL_argcheck(L, (interval > 0 && interval <= MAX_TIMEOUT), 2, MAX_TIMEOUT_ERR_STR);
if(tmr->mode != TIMER_MODE_OFF){
......@@ -230,11 +263,10 @@ static int tmr_interval(lua_State* L){
return 0;
}
// Lua: tmr.state( id )
// Lua: tmr.state( id / ref )
static int tmr_state(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
timer_t tmr = tmr_get(L, 1);
if(tmr->mode == TIMER_MODE_OFF){
lua_pushnil(L);
return 1;
......@@ -307,8 +339,34 @@ static int tmr_softwd( lua_State* L ){
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
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[] = {
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
......@@ -321,7 +379,8 @@ static const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
{ LSTRKEY( "unregister" ), LFUNCVAL( tmr_unregister ) },
{ 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_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) },
{ LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) },
......@@ -330,8 +389,12 @@ static const LUA_REG_TYPE tmr_map[] = {
int luaopen_tmr( lua_State *L ){
int i;
luaL_rometatable(L, "tmr.timer", (void *)tmr_dyn_map);
for(i=0; i<NUM_TMR; i++){
alarm_timers[i].lua_ref = LUA_NOREF;
alarm_timers[i].self_ref = LUA_REFNIL;
alarm_timers[i].mode = TIMER_MODE_OFF;
ets_timer_disarm(&alarm_timers[i].os);
}
......
......@@ -238,6 +238,19 @@ static int lu8g_getMode( lua_State *L )
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 )
static int lu8g_setColorIndex( lua_State *L )
{
......@@ -1086,6 +1099,7 @@ static const LUA_REG_TYPE lu8g_display_map[] = {
{ LSTRKEY( "getStrWidth" ), LFUNCVAL( lu8g_getStrWidth ) },
{ LSTRKEY( "getWidth" ), LFUNCVAL( lu8g_getWidth ) },
{ LSTRKEY( "nextPage" ), LFUNCVAL( lu8g_nextPage ) },
{ LSTRKEY( "setContrast" ), LFUNCVAL( lu8g_setContrast ) },
{ LSTRKEY( "setColorIndex" ), LFUNCVAL( lu8g_setColorIndex ) },
{ LSTRKEY( "setDefaultBackgroundColor" ), LFUNCVAL( lu8g_setDefaultBackgroundColor ) },
{ LSTRKEY( "setDefaultForegroundColor" ), LFUNCVAL( lu8g_setDefaultForegroundColor ) },
......
......@@ -8,7 +8,6 @@
#include "c_string.h"
#include "rom.h"
static lua_State *gL = NULL;
static int uart_receive_rf = LUA_NOREF;
bool run_input = true;
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;
if(uart_receive_rf == LUA_NOREF)
return false;
if(!gL)
lua_State *L = lua_getstate();
if(!L)
return false;
lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_receive_rf);
lua_pushlstring(gL, buf, len);
lua_call(gL, 1, 0);
lua_rawgeti(L, LUA_REGISTRYINDEX, uart_receive_rf);
lua_pushlstring(L, buf, len);
lua_call(L, 1, 0);
return !run_input;
}
......@@ -75,7 +75,6 @@ static int uart_on( lua_State* L )
}
if(!lua_isnil(L, -1)){
uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
gL = L;
if(run==0)
run_input = false;
} 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)
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()
static int wifi_getmac( lua_State* L, uint8_t mode )
{
......@@ -1268,6 +1288,7 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LSTRKEY( "setphymode" ), LFUNCVAL( wifi_setphymode ) },
{ LSTRKEY( "getphymode" ), LFUNCVAL( wifi_getphymode ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( wifi_sleep ) },
{ LSTRKEY( "nullmodesleep" ), LFUNCVAL( wifi_null_mode_auto_sleep ) },
#ifdef WIFI_SMART_ENABLE
{ LSTRKEY( "startsmart" ), LFUNCVAL( wifi_start_smart ) },
{ LSTRKEY( "stopsmart" ), LFUNCVAL( wifi_exit_smart ) },
......@@ -1349,6 +1370,12 @@ void wifi_change_default_host_name(void)
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)
wifi_eventmon_init();
#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 ){
// *****************************************************************************
// 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 );
return 1;
......@@ -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 );
}
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 )
{
if (offset + bitlen > 512)
......
......@@ -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 );
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 );
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,
......
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