Unverified Commit 310faf7f authored by Terry Ellison's avatar Terry Ellison Committed by GitHub
Browse files

Merge pull request #2886 from nodemcu/dev

Next master drop
parents 68c425c0 a08e74d9
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "c_string.h" #include <string.h>
#include "c_stdlib.h" #include <stdlib.h>
#include <alloca.h>
#include "c_types.h" #include <stdint.h>
#include "mem.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "nodemcu_mdns.h" #include "nodemcu_mdns.h"
#include "user_interface.h" #include "user_interface.h"
...@@ -43,16 +43,16 @@ static int mdns_register(lua_State *L) ...@@ -43,16 +43,16 @@ static int mdns_register(lua_State *L)
luaL_checktype(L, -2, LUA_TSTRING); luaL_checktype(L, -2, LUA_TSTRING);
const char *key = luaL_checkstring(L, -2); const char *key = luaL_checkstring(L, -2);
if (c_strcmp(key, "port") == 0) { if (strcmp(key, "port") == 0) {
info.service_port = luaL_checknumber(L, -1); info.service_port = luaL_checknumber(L, -1);
} else if (c_strcmp(key, "service") == 0) { } else if (strcmp(key, "service") == 0) {
info.service_name = luaL_checkstring(L, -1); info.service_name = luaL_checkstring(L, -1);
} else if (c_strcmp(key, "description") == 0) { } else if (strcmp(key, "description") == 0) {
info.host_desc = luaL_checkstring(L, -1); info.host_desc = luaL_checkstring(L, -1);
} else { } else {
int len = c_strlen(key) + 1; int len = strlen(key) + 1;
const char *value = luaL_checkstring(L, -1); const char *value = luaL_checkstring(L, -1);
char *p = alloca(len + c_strlen(value) + 1); char *p = alloca(len + strlen(value) + 1);
strcpy(p, key); strcpy(p, key);
strcat(p, "="); strcat(p, "=");
strcat(p, value); strcat(p, value);
...@@ -88,10 +88,10 @@ static int mdns_register(lua_State *L) ...@@ -88,10 +88,10 @@ static int mdns_register(lua_State *L)
} }
// Module function map // Module function map
static const LUA_REG_TYPE mdns_map[] = { LROT_BEGIN(mdns)
{ LSTRKEY("register"), LFUNCVAL(mdns_register) }, LROT_FUNCENTRY( register, mdns_register )
{ LSTRKEY("close"), LFUNCVAL(mdns_close) }, LROT_FUNCENTRY( close, mdns_close )
{ LNILKEY, LNILVAL } LROT_END( mdns, NULL, 0 )
};
NODEMCU_MODULE(MDNS, "mdns", mdns_map, NULL);
NODEMCU_MODULE(MDNS, "mdns", mdns, NULL);
...@@ -4,16 +4,16 @@ ...@@ -4,16 +4,16 @@
#include "lauxlib.h" #include "lauxlib.h"
#include "platform.h" #include "platform.h"
#include "c_string.h" #include <string.h>
#include "c_stdlib.h" #include <stddef.h>
#include "c_types.h" #include <stdint.h>
#include "mem.h" #include "mem.h"
#include "lwip/ip_addr.h" #include "lwip/ip_addr.h"
#include "espconn.h" #include "espconn.h"
#include "mqtt_msg.h" #include "mqtt/mqtt_msg.h"
#include "msg_queue.h" #include "mqtt/msg_queue.h"
#include "user_interface.h" #include "user_interface.h"
...@@ -50,10 +50,6 @@ typedef struct mqtt_event_data_t ...@@ -50,10 +50,6 @@ typedef struct mqtt_event_data_t
uint16_t data_offset; uint16_t data_offset;
} mqtt_event_data_t; } mqtt_event_data_t;
#define RECONNECT_OFF 0
#define RECONNECT_POSSIBLE 1
#define RECONNECT_ON 2
typedef enum { typedef enum {
MQTT_RECV_NORMAL, MQTT_RECV_NORMAL,
MQTT_RECV_BUFFERING_SHORT, MQTT_RECV_BUFFERING_SHORT,
...@@ -64,7 +60,6 @@ typedef enum { ...@@ -64,7 +60,6 @@ typedef enum {
typedef struct mqtt_state_t typedef struct mqtt_state_t
{ {
uint16_t port; uint16_t port;
uint8_t auto_reconnect; // 0 is not auto_reconnect. 1 is auto reconnect, but never connected. 2 is auto reconnect, but once connected
mqtt_connect_info_t* connect_info; mqtt_connect_info_t* connect_info;
mqtt_connection_t mqtt_connection; mqtt_connection_t mqtt_connection;
msg_queue_t* pending_msg_q; msg_queue_t* pending_msg_q;
...@@ -138,36 +133,24 @@ static void mqtt_socket_disconnected(void *arg) // tcp only ...@@ -138,36 +133,24 @@ static void mqtt_socket_disconnected(void *arg) // tcp only
} }
if(mud->mqtt_state.recv_buffer) { if(mud->mqtt_state.recv_buffer) {
c_free(mud->mqtt_state.recv_buffer); free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer = NULL;
} }
mud->mqtt_state.recv_buffer_size = 0; mud->mqtt_state.recv_buffer_size = 0;
mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL; mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL;
if(mud->mqtt_state.auto_reconnect == RECONNECT_ON) {
mud->pesp_conn->reverse = mud;
mud->pesp_conn->type = ESPCONN_TCP;
mud->pesp_conn->state = ESPCONN_NONE;
mud->connected = false;
mud->pesp_conn->proto.tcp->remote_port = mud->mqtt_state.port;
mud->pesp_conn->proto.tcp->local_port = espconn_port();
espconn_regist_connectcb(mud->pesp_conn, mqtt_socket_connected);
espconn_regist_reconcb(mud->pesp_conn, mqtt_socket_reconnected);
socket_connect(pesp_conn);
} else {
if(mud->pesp_conn){ if(mud->pesp_conn){
mud->pesp_conn->reverse = NULL; mud->pesp_conn->reverse = NULL;
if(mud->pesp_conn->proto.tcp) if(mud->pesp_conn->proto.tcp)
c_free(mud->pesp_conn->proto.tcp); free(mud->pesp_conn->proto.tcp);
mud->pesp_conn->proto.tcp = NULL; mud->pesp_conn->proto.tcp = NULL;
c_free(mud->pesp_conn); free(mud->pesp_conn);
mud->pesp_conn = NULL; mud->pesp_conn = NULL;
} }
mud->connected = false; 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
}
if(call_back){ if(call_back){
lua_call(L, 1, 0); lua_call(L, 1, 0);
...@@ -191,11 +174,6 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err) ...@@ -191,11 +174,6 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
mud->event_timeout = 0; // no need to count anymore mud->event_timeout = 0; // no need to count anymore
if(mud->mqtt_state.auto_reconnect == RECONNECT_ON) {
pesp_conn->proto.tcp->remote_port = mud->mqtt_state.port;
pesp_conn->proto.tcp->local_port = espconn_port();
socket_connect(pesp_conn);
} else {
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
if (mud->secure) { if (mud->secure) {
espconn_secure_disconnect(pesp_conn); espconn_secure_disconnect(pesp_conn);
...@@ -208,7 +186,6 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err) ...@@ -208,7 +186,6 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND); mqtt_connack_fail(mud, MQTT_CONN_FAIL_SERVER_NOT_FOUND);
mqtt_socket_disconnected(arg); mqtt_socket_disconnected(arg);
}
NODE_DBG("leave mqtt_socket_reconnected.\n"); NODE_DBG("leave mqtt_socket_reconnected.\n");
} }
...@@ -326,7 +303,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) ...@@ -326,7 +303,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len)
// Last buffer had so few byte that we could not determine message length. // Last buffer had so few byte that we could not determine message length.
// Store in a local heap buffer and operate on this, as if was the regular pdata buffer. // Store in a local heap buffer and operate on this, as if was the regular pdata buffer.
// Avoids having to repeat message size/overflow logic. // Avoids having to repeat message size/overflow logic.
temp_pdata = c_zalloc(mud->mqtt_state.recv_buffer_size + len); temp_pdata = calloc(1,mud->mqtt_state.recv_buffer_size + len);
if(temp_pdata == NULL) { if(temp_pdata == NULL) {
NODE_DBG("MQTT[buffering-short]: Failed to allocate %u bytes, disconnecting...\n", mud->mqtt_state.recv_buffer_size + len); NODE_DBG("MQTT[buffering-short]: Failed to allocate %u bytes, disconnecting...\n", mud->mqtt_state.recv_buffer_size + len);
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
...@@ -343,7 +320,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len) ...@@ -343,7 +320,7 @@ static void mqtt_socket_received(void *arg, char *pdata, unsigned short len)
NODE_DBG("MQTT[buffering-short]: Continuing with %u + %u bytes\n", mud->mqtt_state.recv_buffer_size, len); NODE_DBG("MQTT[buffering-short]: Continuing with %u + %u bytes\n", mud->mqtt_state.recv_buffer_size, len);
memcpy(temp_pdata, mud->mqtt_state.recv_buffer, mud->mqtt_state.recv_buffer_size); memcpy(temp_pdata, mud->mqtt_state.recv_buffer, mud->mqtt_state.recv_buffer_size);
memcpy(temp_pdata + mud->mqtt_state.recv_buffer_size, pdata, len); memcpy(temp_pdata + mud->mqtt_state.recv_buffer_size, pdata, len);
c_free(mud->mqtt_state.recv_buffer); free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer = NULL;
mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL; mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL;
...@@ -475,9 +452,6 @@ READPACKET: ...@@ -475,9 +452,6 @@ READPACKET:
mud->keepalive_sent = 0; mud->keepalive_sent = 0;
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_connect_fail_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_connect_fail_ref);
mud->cb_connect_fail_ref = LUA_NOREF; mud->cb_connect_fail_ref = LUA_NOREF;
if (mud->mqtt_state.auto_reconnect == RECONNECT_POSSIBLE) {
mud->mqtt_state.auto_reconnect = RECONNECT_ON;
}
if(mud->cb_connect_ref == LUA_NOREF) if(mud->cb_connect_ref == LUA_NOREF)
break; break;
if(mud->self_ref == LUA_NOREF) if(mud->self_ref == LUA_NOREF)
...@@ -559,7 +533,7 @@ READPACKET: ...@@ -559,7 +533,7 @@ READPACKET:
// max_message_length is 16bit. // max_message_length is 16bit.
uint16_t alloc_size = message_length > 0 ? (uint16_t)message_length : in_buffer_length; uint16_t alloc_size = message_length > 0 ? (uint16_t)message_length : in_buffer_length;
mud->mqtt_state.recv_buffer = c_zalloc(alloc_size); mud->mqtt_state.recv_buffer = calloc(1,alloc_size);
if (mud->mqtt_state.recv_buffer == NULL) { if (mud->mqtt_state.recv_buffer == NULL) {
NODE_DBG("MQTT: Failed to allocate %u bytes, disconnecting...\n", alloc_size); NODE_DBG("MQTT: Failed to allocate %u bytes, disconnecting...\n", alloc_size);
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
...@@ -700,7 +674,7 @@ RX_MESSAGE_PROCESSED: ...@@ -700,7 +674,7 @@ RX_MESSAGE_PROCESSED:
if(continuation_buffer != NULL) { if(continuation_buffer != NULL) {
NODE_DBG("MQTT[buffering]: buffered message finished. Continuing with rest of rx buffer (%u)\n", NODE_DBG("MQTT[buffering]: buffered message finished. Continuing with rest of rx buffer (%u)\n",
len); len);
c_free(mud->mqtt_state.recv_buffer); free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer = NULL;
in_buffer = continuation_buffer; in_buffer = continuation_buffer;
...@@ -724,7 +698,7 @@ RX_MESSAGE_PROCESSED: ...@@ -724,7 +698,7 @@ RX_MESSAGE_PROCESSED:
RX_PACKET_FINISHED: RX_PACKET_FINISHED:
if(temp_pdata != NULL) { if(temp_pdata != NULL) {
c_free(temp_pdata); free(temp_pdata);
} }
mqtt_send_if_possible(pesp_conn); mqtt_send_if_possible(pesp_conn);
...@@ -928,12 +902,12 @@ static int mqtt_socket_client( lua_State* L ) ...@@ -928,12 +902,12 @@ static int mqtt_socket_client( lua_State* L )
lmqtt_userdata *mud; lmqtt_userdata *mud;
char tempid[20] = {0}; char tempid[20] = {0};
c_sprintf(tempid, "%s%x", "NodeMCU_", system_get_chip_id() ); sprintf(tempid, "%s%x", "NodeMCU_", system_get_chip_id() );
NODE_DBG(tempid); NODE_DBG(tempid);
NODE_DBG("\n"); NODE_DBG("\n");
const char *clientId = tempid, *username = NULL, *password = NULL; const char *clientId = tempid, *username = NULL, *password = NULL;
size_t idl = c_strlen(tempid); size_t idl = strlen(tempid);
size_t unl = 0, pwl = 0; size_t unl = 0, pwl = 0;
int keepalive = 0; int keepalive = 0;
int stack = 1; int stack = 1;
...@@ -943,7 +917,7 @@ static int mqtt_socket_client( lua_State* L ) ...@@ -943,7 +917,7 @@ static int mqtt_socket_client( lua_State* L )
// create a object // create a object
mud = (lmqtt_userdata *)lua_newuserdata(L, sizeof(lmqtt_userdata)); mud = (lmqtt_userdata *)lua_newuserdata(L, sizeof(lmqtt_userdata));
c_memset(mud, 0, sizeof(*mud)); memset(mud, 0, sizeof(*mud));
// pre-initialize it, in case of errors // pre-initialize it, in case of errors
mud->self_ref = LUA_NOREF; mud->self_ref = LUA_NOREF;
mud->cb_connect_ref = LUA_NOREF; mud->cb_connect_ref = LUA_NOREF;
...@@ -1015,30 +989,30 @@ static int mqtt_socket_client( lua_State* L ) ...@@ -1015,30 +989,30 @@ static int mqtt_socket_client( lua_State* L )
} }
// TODO: check the zalloc result. // TODO: check the zalloc result.
mud->connect_info.client_id = (uint8_t *)c_zalloc(idl+1); mud->connect_info.client_id = (uint8_t *)calloc(1,idl+1);
mud->connect_info.username = (uint8_t *)c_zalloc(unl + 1); mud->connect_info.username = (uint8_t *)calloc(1,unl + 1);
mud->connect_info.password = (uint8_t *)c_zalloc(pwl + 1); mud->connect_info.password = (uint8_t *)calloc(1,pwl + 1);
if(!mud->connect_info.client_id || !mud->connect_info.username || !mud->connect_info.password){ if(!mud->connect_info.client_id || !mud->connect_info.username || !mud->connect_info.password){
if(mud->connect_info.client_id) { if(mud->connect_info.client_id) {
c_free(mud->connect_info.client_id); free(mud->connect_info.client_id);
mud->connect_info.client_id = NULL; mud->connect_info.client_id = NULL;
} }
if(mud->connect_info.username) { if(mud->connect_info.username) {
c_free(mud->connect_info.username); free(mud->connect_info.username);
mud->connect_info.username = NULL; mud->connect_info.username = NULL;
} }
if(mud->connect_info.password) { if(mud->connect_info.password) {
c_free(mud->connect_info.password); free(mud->connect_info.password);
mud->connect_info.password = NULL; mud->connect_info.password = NULL;
} }
return luaL_error(L, "not enough memory"); return luaL_error(L, "not enough memory");
} }
c_memcpy(mud->connect_info.client_id, clientId, idl); memcpy(mud->connect_info.client_id, clientId, idl);
mud->connect_info.client_id[idl] = 0; mud->connect_info.client_id[idl] = 0;
c_memcpy(mud->connect_info.username, username, unl); memcpy(mud->connect_info.username, username, unl);
mud->connect_info.username[unl] = 0; mud->connect_info.username[unl] = 0;
c_memcpy(mud->connect_info.password, password, pwl); memcpy(mud->connect_info.password, password, pwl);
mud->connect_info.password[pwl] = 0; mud->connect_info.password[pwl] = 0;
NODE_DBG("MQTT: Init info: %s, %s, %s\r\n", mud->connect_info.client_id, mud->connect_info.username, mud->connect_info.password); NODE_DBG("MQTT: Init info: %s, %s, %s\r\n", mud->connect_info.client_id, mud->connect_info.username, mud->connect_info.password);
...@@ -1050,7 +1024,6 @@ static int mqtt_socket_client( lua_State* L ) ...@@ -1050,7 +1024,6 @@ static int mqtt_socket_client( lua_State* L )
mud->connect_info.max_message_length = max_message_length; mud->connect_info.max_message_length = max_message_length;
mud->mqtt_state.pending_msg_q = NULL; mud->mqtt_state.pending_msg_q = NULL;
mud->mqtt_state.auto_reconnect = RECONNECT_OFF;
mud->mqtt_state.port = 1883; mud->mqtt_state.port = 1883;
mud->mqtt_state.connect_info = &mud->connect_info; mud->mqtt_state.connect_info = &mud->connect_info;
mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer = NULL;
...@@ -1082,9 +1055,9 @@ static int mqtt_delete( lua_State* L ) ...@@ -1082,9 +1055,9 @@ static int mqtt_delete( lua_State* L )
if(mud->pesp_conn){ // for client connected to tcp server, this should set NULL in disconnect cb if(mud->pesp_conn){ // for client connected to tcp server, this should set NULL in disconnect cb
mud->pesp_conn->reverse = NULL; mud->pesp_conn->reverse = NULL;
if(mud->pesp_conn->proto.tcp) if(mud->pesp_conn->proto.tcp)
c_free(mud->pesp_conn->proto.tcp); free(mud->pesp_conn->proto.tcp);
mud->pesp_conn->proto.tcp = NULL; mud->pesp_conn->proto.tcp = NULL;
c_free(mud->pesp_conn); 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) { while(mud->mqtt_state.pending_msg_q) {
...@@ -1093,34 +1066,34 @@ static int mqtt_delete( lua_State* L ) ...@@ -1093,34 +1066,34 @@ static int mqtt_delete( lua_State* L )
// ---- alloc-ed in mqtt_socket_lwt() // ---- alloc-ed in mqtt_socket_lwt()
if(mud->connect_info.will_topic){ if(mud->connect_info.will_topic){
c_free(mud->connect_info.will_topic); free(mud->connect_info.will_topic);
mud->connect_info.will_topic = NULL; mud->connect_info.will_topic = NULL;
} }
if(mud->connect_info.will_message){ if(mud->connect_info.will_message){
c_free(mud->connect_info.will_message); free(mud->connect_info.will_message);
mud->connect_info.will_message = NULL; mud->connect_info.will_message = NULL;
} }
// ---- // ----
//--------- alloc-ed in mqtt_socket_received() //--------- alloc-ed in mqtt_socket_received()
if(mud->mqtt_state.recv_buffer) { if(mud->mqtt_state.recv_buffer) {
c_free(mud->mqtt_state.recv_buffer); free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL; mud->mqtt_state.recv_buffer = NULL;
} }
// ---- // ----
//--------- alloc-ed in mqtt_socket_client() //--------- alloc-ed in mqtt_socket_client()
if(mud->connect_info.client_id){ if(mud->connect_info.client_id){
c_free(mud->connect_info.client_id); free(mud->connect_info.client_id);
mud->connect_info.client_id = NULL; mud->connect_info.client_id = NULL;
} }
if(mud->connect_info.username){ if(mud->connect_info.username){
c_free(mud->connect_info.username); free(mud->connect_info.username);
mud->connect_info.username = NULL; mud->connect_info.username = NULL;
} }
if(mud->connect_info.password){ if(mud->connect_info.password){
c_free(mud->connect_info.password); free(mud->connect_info.password);
mud->connect_info.password = NULL; mud->connect_info.password = NULL;
} }
// ------- // -------
...@@ -1230,7 +1203,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -1230,7 +1203,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
if(ipaddr->addr != 0) if(ipaddr->addr != 0)
{ {
dns_reconn_count = 0; dns_reconn_count = 0;
c_memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4); memcpy(pesp_conn->proto.tcp->remote_ip, &(ipaddr->addr), 4);
NODE_DBG("TCP ip is set: "); NODE_DBG("TCP ip is set: ");
NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr))); NODE_DBG(IPSTR, IP2STR(&(ipaddr->addr)));
NODE_DBG("\n"); NODE_DBG("\n");
...@@ -1242,7 +1215,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) ...@@ -1242,7 +1215,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
} }
#include "pm/swtimer.h" #include "pm/swtimer.h"
// Lua: mqtt:connect( host, port, secure, auto_reconnect, function(client), function(client, connect_return_code) ) // Lua: mqtt:connect( host, port, secure, function(client), function(client, connect_return_code) )
static int mqtt_socket_connect( lua_State* L ) static int mqtt_socket_connect( lua_State* L )
{ {
NODE_DBG("enter mqtt_socket_connect.\n"); NODE_DBG("enter mqtt_socket_connect.\n");
...@@ -1252,7 +1225,7 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1252,7 +1225,7 @@ static int mqtt_socket_connect( lua_State* L )
ip_addr_t ipaddr; ip_addr_t ipaddr;
const char *domain; const char *domain;
int stack = 1; int stack = 1;
unsigned secure = 0, auto_reconnect = RECONNECT_OFF; unsigned secure = 0;
int top = lua_gettop(L); int top = lua_gettop(L);
sint8 espconn_status; sint8 espconn_status;
...@@ -1268,7 +1241,7 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1268,7 +1241,7 @@ static int mqtt_socket_connect( lua_State* L )
struct espconn *pesp_conn = mud->pesp_conn; struct espconn *pesp_conn = mud->pesp_conn;
if(!pesp_conn) { if(!pesp_conn) {
pesp_conn = mud->pesp_conn = (struct espconn *)c_zalloc(sizeof(struct espconn)); pesp_conn = mud->pesp_conn = (struct espconn *)calloc(1,sizeof(struct espconn));
} else { } else {
espconn_delete(pesp_conn); espconn_delete(pesp_conn);
} }
...@@ -1276,9 +1249,9 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1276,9 +1249,9 @@ static int mqtt_socket_connect( lua_State* L )
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) if (!pesp_conn->proto.tcp)
pesp_conn->proto.tcp = (esp_tcp *)c_zalloc(sizeof(esp_tcp)); pesp_conn->proto.tcp = (esp_tcp *)calloc(1,sizeof(esp_tcp));
if(!pesp_conn->proto.tcp){ if(!pesp_conn->proto.tcp){
c_free(pesp_conn); free(pesp_conn);
pesp_conn = mud->pesp_conn = NULL; pesp_conn = mud->pesp_conn = NULL;
return luaL_error(L, "not enough memory"); return luaL_error(L, "not enough memory");
} }
...@@ -1298,7 +1271,7 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1298,7 +1271,7 @@ static int mqtt_socket_connect( lua_State* L )
domain = "127.0.0.1"; domain = "127.0.0.1";
} }
ipaddr.addr = ipaddr_addr(domain); ipaddr.addr = ipaddr_addr(domain);
c_memcpy(pesp_conn->proto.tcp->remote_ip, &ipaddr.addr, 4); memcpy(pesp_conn->proto.tcp->remote_ip, &ipaddr.addr, 4);
NODE_DBG("TCP ip is set: "); NODE_DBG("TCP ip is set: ");
NODE_DBG(IPSTR, IP2STR(&ipaddr.addr)); NODE_DBG(IPSTR, IP2STR(&ipaddr.addr));
NODE_DBG("\n"); NODE_DBG("\n");
...@@ -1315,13 +1288,15 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1315,13 +1288,15 @@ static int mqtt_socket_connect( lua_State* L )
pesp_conn->proto.tcp->local_port = espconn_port(); 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) || lua_isboolean(L, stack)) )
{ {
secure = lua_tointeger(L, stack); if (lua_isnumber(L, stack)) {
stack++; platform_print_deprecation_note("mqtt.connect secure parameter as integer","in the future");
if ( secure != 0 && secure != 1 ){ secure = !!lua_tointeger(L, stack);
secure = 0; // default to 0 } else {
secure = lua_toboolean(L, stack);
} }
stack++;
} else { } else {
secure = 0; // default to 0 secure = 0; // default to 0
} }
...@@ -1334,19 +1309,6 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1334,19 +1309,6 @@ static int mqtt_socket_connect( lua_State* L )
} }
#endif #endif
if ( (stack<=top) && lua_isnumber(L, stack) )
{
platform_print_deprecation_note("autoreconnect is deprecated", "in the next version");
auto_reconnect = lua_tointeger(L, stack);
stack++;
if ( auto_reconnect != RECONNECT_OFF && auto_reconnect != RECONNECT_POSSIBLE ){
auto_reconnect = RECONNECT_OFF; // default to 0
}
} else {
auto_reconnect = RECONNECT_OFF; // default to 0
}
mud->mqtt_state.auto_reconnect = auto_reconnect;
// call back function when a connection is obtained, tcp only // call back function when a connection is obtained, tcp only
if ((stack<=top) && (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION)){ if ((stack<=top) && (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION)){
lua_pushvalue(L, stack); // copy argument (func) to the top of stack lua_pushvalue(L, stack); // copy argument (func) to the top of stack
...@@ -1378,7 +1340,7 @@ static int mqtt_socket_connect( lua_State* L ) ...@@ -1378,7 +1340,7 @@ static int mqtt_socket_connect( lua_State* L )
//My guess: If in doubt, resume the timer //My guess: If in doubt, resume the timer
// timer started in socket_connect() // timer started in socket_connect()
if((ipaddr.addr == IPADDR_NONE) && (c_memcmp(domain,"255.255.255.255",16) != 0)) if((ipaddr.addr == IPADDR_NONE) && (memcmp(domain,"255.255.255.255",16) != 0))
{ {
host_ip.addr = 0; host_ip.addr = 0;
dns_reconn_count = 0; dns_reconn_count = 0;
...@@ -1416,8 +1378,6 @@ static int mqtt_socket_close( lua_State* L ) ...@@ -1416,8 +1378,6 @@ static int mqtt_socket_close( lua_State* L )
return 1; return 1;
} }
mud->mqtt_state.auto_reconnect = RECONNECT_OFF; // stop auto reconnect.
sint8 espconn_status = ESPCONN_CONN; sint8 espconn_status = ESPCONN_CONN;
if (mud->connected) { if (mud->connected) {
// Send disconnect message // Send disconnect message
...@@ -1474,18 +1434,27 @@ static int mqtt_socket_on( lua_State* L ) ...@@ -1474,18 +1434,27 @@ static int mqtt_socket_on( lua_State* L )
luaL_checkanyfunction(L, 3); luaL_checkanyfunction(L, 3);
lua_pushvalue(L, 3); // copy argument (func) to the top of stack lua_pushvalue(L, 3); // copy argument (func) to the top of stack
if( sl == 7 && c_strcmp(method, "connect") == 0){ if( sl == 7 && strcmp(method, "connect") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_connect_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_connect_ref);
mud->cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX); mud->cb_connect_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 7 && c_strcmp(method, "offline") == 0){ }else if( sl == 7 && strcmp(method, "offline") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_disconnect_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_disconnect_ref);
mud->cb_disconnect_ref = luaL_ref(L, LUA_REGISTRYINDEX); mud->cb_disconnect_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 7 && c_strcmp(method, "message") == 0){ }else if( sl == 7 && strcmp(method, "message") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_message_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_message_ref);
mud->cb_message_ref = luaL_ref(L, LUA_REGISTRYINDEX); mud->cb_message_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 8 && c_strcmp(method, "overflow") == 0){ }else if( sl == 8 && strcmp(method, "overflow") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_overflow_ref); luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_overflow_ref);
mud->cb_overflow_ref = luaL_ref(L, LUA_REGISTRYINDEX); mud->cb_overflow_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 6 && strcmp(method, "puback") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_puback_ref);
mud->cb_puback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 6 && strcmp(method, "suback") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_suback_ref);
mud->cb_suback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else if( sl == 8 && strcmp(method, "unsuback") == 0){
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_unsuback_ref);
mud->cb_unsuback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}else{ }else{
lua_pop(L, 1); lua_pop(L, 1);
return luaL_error( L, "method not supported" ); return luaL_error( L, "method not supported" );
...@@ -1826,30 +1795,30 @@ static int mqtt_socket_lwt( lua_State* L ) ...@@ -1826,30 +1795,30 @@ static int mqtt_socket_lwt( lua_State* L )
} }
stack++; stack++;
if(mud->connect_info.will_topic){ // free the previous one if there is any if(mud->connect_info.will_topic){ // free the previous one if there is any
c_free(mud->connect_info.will_topic); free(mud->connect_info.will_topic);
mud->connect_info.will_topic = NULL; mud->connect_info.will_topic = NULL;
} }
if(mud->connect_info.will_message){ if(mud->connect_info.will_message){
c_free(mud->connect_info.will_message); free(mud->connect_info.will_message);
mud->connect_info.will_message = NULL; mud->connect_info.will_message = NULL;
} }
mud->connect_info.will_topic = (uint8_t*) c_zalloc( topicSize + 1 ); mud->connect_info.will_topic = (uint8_t*) calloc(1, topicSize + 1 );
mud->connect_info.will_message = (uint8_t*) c_zalloc( msgSize + 1 ); mud->connect_info.will_message = (uint8_t*) calloc(1, msgSize + 1 );
if(!mud->connect_info.will_topic || !mud->connect_info.will_message){ if(!mud->connect_info.will_topic || !mud->connect_info.will_message){
if(mud->connect_info.will_topic){ if(mud->connect_info.will_topic){
c_free(mud->connect_info.will_topic); free(mud->connect_info.will_topic);
mud->connect_info.will_topic = NULL; mud->connect_info.will_topic = NULL;
} }
if(mud->connect_info.will_message){ if(mud->connect_info.will_message){
c_free(mud->connect_info.will_message); free(mud->connect_info.will_message);
mud->connect_info.will_message = NULL; mud->connect_info.will_message = NULL;
} }
return luaL_error( L, "not enough memory"); return luaL_error( L, "not enough memory");
} }
c_memcpy(mud->connect_info.will_topic, lwtTopic, topicSize); memcpy(mud->connect_info.will_topic, lwtTopic, topicSize);
mud->connect_info.will_topic[topicSize] = 0; mud->connect_info.will_topic[topicSize] = 0;
c_memcpy(mud->connect_info.will_message, lwtMsg, msgSize); memcpy(mud->connect_info.will_message, lwtMsg, msgSize);
mud->connect_info.will_message[msgSize] = 0; mud->connect_info.will_message[msgSize] = 0;
if ( lua_isnumber(L, stack) ) if ( lua_isnumber(L, stack) )
...@@ -1873,43 +1842,43 @@ static int mqtt_socket_lwt( lua_State* L ) ...@@ -1873,43 +1842,43 @@ static int mqtt_socket_lwt( lua_State* L )
} }
// Module function map // Module function map
static const LUA_REG_TYPE mqtt_socket_map[] = { LROT_BEGIN(mqtt_socket)
{ LSTRKEY( "connect" ), LFUNCVAL( mqtt_socket_connect ) }, LROT_FUNCENTRY( connect, mqtt_socket_connect )
{ LSTRKEY( "close" ), LFUNCVAL( mqtt_socket_close ) }, LROT_FUNCENTRY( close, mqtt_socket_close )
{ LSTRKEY( "publish" ), LFUNCVAL( mqtt_socket_publish ) }, LROT_FUNCENTRY( publish, mqtt_socket_publish )
{ LSTRKEY( "subscribe" ), LFUNCVAL( mqtt_socket_subscribe ) }, LROT_FUNCENTRY( subscribe, mqtt_socket_subscribe )
{ LSTRKEY( "unsubscribe" ), LFUNCVAL( mqtt_socket_unsubscribe ) }, LROT_FUNCENTRY( unsubscribe, mqtt_socket_unsubscribe )
{ LSTRKEY( "lwt" ), LFUNCVAL( mqtt_socket_lwt ) }, LROT_FUNCENTRY( lwt, mqtt_socket_lwt )
{ LSTRKEY( "on" ), LFUNCVAL( mqtt_socket_on ) }, LROT_FUNCENTRY( on, mqtt_socket_on )
{ LSTRKEY( "__gc" ), LFUNCVAL( mqtt_delete ) }, LROT_FUNCENTRY( __gc, mqtt_delete )
{ LSTRKEY( "__index" ), LROVAL( mqtt_socket_map ) }, LROT_TABENTRY( __index, mqtt_socket )
{ LNILKEY, LNILVAL } LROT_END( mqtt_socket, mqtt_socket, 0 )
};
static const LUA_REG_TYPE mqtt_map[] = { LROT_BEGIN(mqtt)
{ LSTRKEY( "Client" ), LFUNCVAL( mqtt_socket_client ) }, LROT_FUNCENTRY( Client, mqtt_socket_client )
{ LSTRKEY( "CONN_FAIL_SERVER_NOT_FOUND" ), LNUMVAL( MQTT_CONN_FAIL_SERVER_NOT_FOUND ) }, LROT_NUMENTRY( CONN_FAIL_SERVER_NOT_FOUND, MQTT_CONN_FAIL_SERVER_NOT_FOUND )
{ LSTRKEY( "CONN_FAIL_NOT_A_CONNACK_MSG" ), LNUMVAL( MQTT_CONN_FAIL_NOT_A_CONNACK_MSG ) }, LROT_NUMENTRY( CONN_FAIL_NOT_A_CONNACK_MSG, MQTT_CONN_FAIL_NOT_A_CONNACK_MSG )
{ LSTRKEY( "CONN_FAIL_DNS" ), LNUMVAL( MQTT_CONN_FAIL_DNS ) }, LROT_NUMENTRY( CONN_FAIL_DNS, MQTT_CONN_FAIL_DNS )
{ LSTRKEY( "CONN_FAIL_TIMEOUT_RECEIVING" ), LNUMVAL( MQTT_CONN_FAIL_TIMEOUT_RECEIVING ) }, LROT_NUMENTRY( CONN_FAIL_TIMEOUT_RECEIVING, MQTT_CONN_FAIL_TIMEOUT_RECEIVING )
{ LSTRKEY( "CONN_FAIL_TIMEOUT_SENDING" ), LNUMVAL( MQTT_CONN_FAIL_TIMEOUT_SENDING ) }, LROT_NUMENTRY( CONN_FAIL_TIMEOUT_SENDING, MQTT_CONN_FAIL_TIMEOUT_SENDING )
{ LSTRKEY( "CONNACK_ACCEPTED" ), LNUMVAL( MQTT_CONNACK_ACCEPTED ) }, LROT_NUMENTRY( CONNACK_ACCEPTED, MQTT_CONNACK_ACCEPTED )
{ LSTRKEY( "CONNACK_REFUSED_PROTOCOL_VER" ), LNUMVAL( MQTT_CONNACK_REFUSED_PROTOCOL_VER ) }, LROT_NUMENTRY( CONNACK_REFUSED_PROTOCOL_VER, MQTT_CONNACK_REFUSED_PROTOCOL_VER )
{ LSTRKEY( "CONNACK_REFUSED_ID_REJECTED" ), LNUMVAL( MQTT_CONNACK_REFUSED_ID_REJECTED ) }, LROT_NUMENTRY( CONNACK_REFUSED_ID_REJECTED, MQTT_CONNACK_REFUSED_ID_REJECTED )
{ LSTRKEY( "CONNACK_REFUSED_SERVER_UNAVAILABLE" ), LNUMVAL( MQTT_CONNACK_REFUSED_SERVER_UNAVAILABLE ) }, LROT_NUMENTRY( CONNACK_REFUSED_SERVER_UNAVAILABLE, MQTT_CONNACK_REFUSED_SERVER_UNAVAILABLE )
{ LSTRKEY( "CONNACK_REFUSED_BAD_USER_OR_PASS" ), LNUMVAL( MQTT_CONNACK_REFUSED_BAD_USER_OR_PASS ) }, LROT_NUMENTRY( CONNACK_REFUSED_BAD_USER_OR_PASS, MQTT_CONNACK_REFUSED_BAD_USER_OR_PASS )
{ LSTRKEY( "CONNACK_REFUSED_NOT_AUTHORIZED" ), LNUMVAL( MQTT_CONNACK_REFUSED_NOT_AUTHORIZED ) }, LROT_NUMENTRY( CONNACK_REFUSED_NOT_AUTHORIZED, MQTT_CONNACK_REFUSED_NOT_AUTHORIZED )
{ LSTRKEY( "__metatable" ), LROVAL( mqtt_map ) }, LROT_TABENTRY( __metatable, mqtt )
{ LNILKEY, LNILVAL } LROT_END( mqtt, mqtt, 0 )
};
int luaopen_mqtt( lua_State *L ) int luaopen_mqtt( lua_State *L )
{ {
luaL_rometatable(L, "mqtt.socket", (void *)mqtt_socket_map); // create metatable for mqtt.socket luaL_rometatable(L, "mqtt.socket", LROT_TABLEREF(mqtt_socket));
return 0; return 0;
} }
NODEMCU_MODULE(MQTT, "mqtt", mqtt_map, luaopen_mqtt); NODEMCU_MODULE(MQTT, "mqtt", mqtt, luaopen_mqtt);
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
#include "platform.h" #include "platform.h"
#include "lmem.h" #include "lmem.h"
#include "c_string.h" #include <string.h>
#include "c_stdlib.h" #include <strings.h>
#include <stddef.h>
#include "c_types.h" #include <stdint.h>
#include "mem.h" #include "mem.h"
#include "osapi.h" #include "osapi.h"
#include "lwip/err.h" #include "lwip/err.h"
...@@ -875,14 +876,14 @@ static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callbac ...@@ -875,14 +876,14 @@ static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callbac
addr = *ipaddr; addr = *ipaddr;
else addr.addr = 0xFFFFFFFF; else addr.addr = 0xFFFFFFFF;
int cb_ref = ((int*)callback_arg)[0]; int cb_ref = ((int*)callback_arg)[0];
c_free(callback_arg); free(callback_arg);
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref);
lua_pushnil(L); lua_pushnil(L);
if (addr.addr != 0xFFFFFFFF) { if (addr.addr != 0xFFFFFFFF) {
char iptmp[20]; char iptmp[20];
size_t ipl = c_sprintf(iptmp, IPSTR, IP2STR(&addr.addr)); size_t ipl = sprintf(iptmp, IPSTR, IP2STR(&addr.addr));
lua_pushlstring(L, iptmp, ipl); lua_pushlstring(L, iptmp, ipl);
} else { } else {
lua_pushnil(L); lua_pushnil(L);
...@@ -906,7 +907,7 @@ static int net_dns_static( lua_State* L ) { ...@@ -906,7 +907,7 @@ static int net_dns_static( lua_State* L ) {
if (cbref == LUA_NOREF) { if (cbref == LUA_NOREF) {
return luaL_error(L, "wrong callback"); return luaL_error(L, "wrong callback");
} }
int *cbref_ptr = c_zalloc(sizeof(int)); int *cbref_ptr = calloc(1, sizeof(int));
cbref_ptr[0] = cbref; cbref_ptr[0] = cbref;
ip_addr_t addr; ip_addr_t addr;
err_t err = dns_gethostbyname(domain, &addr, net_dns_static_cb, cbref_ptr); err_t err = dns_gethostbyname(domain, &addr, net_dns_static_cb, cbref_ptr);
...@@ -917,7 +918,7 @@ static int net_dns_static( lua_State* L ) { ...@@ -917,7 +918,7 @@ static int net_dns_static( lua_State* L ) {
return 0; return 0;
} else { } else {
int e = lwip_lua_checkerr(L, err); int e = lwip_lua_checkerr(L, err);
c_free(cbref_ptr); free(cbref_ptr);
return e; return e;
} }
return 0; return 0;
...@@ -958,7 +959,7 @@ static int net_getdnsserver( lua_State* L ) { ...@@ -958,7 +959,7 @@ static int net_getdnsserver( lua_State* L ) {
lua_pushnil( L ); lua_pushnil( L );
} else { } else {
char temp[20] = {0}; char temp[20] = {0};
c_sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) ); sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) );
lua_pushstring( L, temp ); lua_pushstring( L, temp );
} }
...@@ -968,79 +969,79 @@ static int net_getdnsserver( lua_State* L ) { ...@@ -968,79 +969,79 @@ static int net_getdnsserver( lua_State* L ) {
#pragma mark - Tables #pragma mark - Tables
#ifdef TLS_MODULE_PRESENT #ifdef TLS_MODULE_PRESENT
extern const LUA_REG_TYPE tls_cert_map[]; LROT_EXTERN(tls_cert);
#endif #endif
// Module function map // Module function map
static const LUA_REG_TYPE net_tcpserver_map[] = { LROT_BEGIN(net_tcpserver)
{ LSTRKEY( "listen" ), LFUNCVAL( net_listen ) }, LROT_FUNCENTRY( listen, net_listen )
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, LROT_FUNCENTRY( getaddr, net_getaddr )
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) }, LROT_FUNCENTRY( close, net_close )
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, LROT_FUNCENTRY( __gc, net_delete )
{ LSTRKEY( "__index" ), LROVAL( net_tcpserver_map ) }, LROT_TABENTRY( __index, net_tcpserver )
{ LNILKEY, LNILVAL } LROT_END( net_tcpserver, net_tcpserver, 0 )
};
static const LUA_REG_TYPE net_tcpsocket_map[] = { LROT_BEGIN(net_tcpsocket)
{ LSTRKEY( "connect" ), LFUNCVAL( net_connect ) }, LROT_FUNCENTRY( connect, net_connect )
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) }, LROT_FUNCENTRY( close, net_close )
{ LSTRKEY( "on" ), LFUNCVAL( net_on ) }, LROT_FUNCENTRY( on, net_on )
{ LSTRKEY( "send" ), LFUNCVAL( net_send ) }, LROT_FUNCENTRY( send, net_send )
{ LSTRKEY( "hold" ), LFUNCVAL( net_hold ) }, LROT_FUNCENTRY( hold, net_hold )
{ LSTRKEY( "unhold" ), LFUNCVAL( net_unhold ) }, LROT_FUNCENTRY( unhold, net_unhold )
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) }, LROT_FUNCENTRY( dns, net_dns )
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) }, LROT_FUNCENTRY( ttl, net_ttl )
{ LSTRKEY( "getpeer" ), LFUNCVAL( net_getpeer ) }, LROT_FUNCENTRY( getpeer, net_getpeer )
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, LROT_FUNCENTRY( getaddr, net_getaddr )
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, LROT_FUNCENTRY( __gc, net_delete )
{ LSTRKEY( "__index" ), LROVAL( net_tcpsocket_map ) }, LROT_TABENTRY( __index, net_tcpsocket )
{ LNILKEY, LNILVAL } LROT_END( net_tcpsocket, net_tcpsocket, 0 )
};
static const LUA_REG_TYPE net_udpsocket_map[] = { LROT_BEGIN(net_udpsocket)
{ LSTRKEY( "listen" ), LFUNCVAL( net_listen ) }, LROT_FUNCENTRY( listen, net_listen )
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) }, LROT_FUNCENTRY( close, net_close )
{ LSTRKEY( "on" ), LFUNCVAL( net_on ) }, LROT_FUNCENTRY( on, net_on )
{ LSTRKEY( "send" ), LFUNCVAL( net_send ) }, LROT_FUNCENTRY( send, net_send )
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) }, LROT_FUNCENTRY( dns, net_dns )
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) }, LROT_FUNCENTRY( ttl, net_ttl )
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) }, LROT_FUNCENTRY( getaddr, net_getaddr )
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) }, LROT_FUNCENTRY( __gc, net_delete )
{ LSTRKEY( "__index" ), LROVAL( net_udpsocket_map ) }, LROT_TABENTRY( __index, net_udpsocket )
{ LNILKEY, LNILVAL } LROT_END( net_udpsocket, net_udpsocket, 0 )
};
static const LUA_REG_TYPE net_dns_map[] = { LROT_BEGIN(net_dns)
{ LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) }, LROT_FUNCENTRY( setdnsserver, net_setdnsserver )
{ LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) }, LROT_FUNCENTRY( getdnsserver, net_getdnsserver )
{ LSTRKEY( "resolve" ), LFUNCVAL( net_dns_static ) }, LROT_FUNCENTRY( resolve, net_dns_static )
{ LNILKEY, LNILVAL } LROT_END( net_dns, net_dns, 0 )
};
static const LUA_REG_TYPE net_map[] = { LROT_BEGIN(net)
{ LSTRKEY( "createServer" ), LFUNCVAL( net_createServer ) }, LROT_FUNCENTRY( createServer, net_createServer )
{ LSTRKEY( "createConnection" ), LFUNCVAL( net_createConnection ) }, LROT_FUNCENTRY( createConnection, net_createConnection )
{ LSTRKEY( "createUDPSocket" ), LFUNCVAL( net_createUDPSocket ) }, LROT_FUNCENTRY( createUDPSocket, net_createUDPSocket )
{ LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) }, LROT_FUNCENTRY( multicastJoin, net_multicastJoin )
{ LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) }, LROT_FUNCENTRY( multicastLeave, net_multicastLeave )
{ LSTRKEY( "dns" ), LROVAL( net_dns_map ) }, LROT_TABENTRY( dns, net_dns )
#ifdef TLS_MODULE_PRESENT #ifdef TLS_MODULE_PRESENT
{ LSTRKEY( "cert" ), LROVAL( tls_cert_map ) }, LROT_TABENTRY( cert, tls_cert )
#endif #endif
{ LSTRKEY( "TCP" ), LNUMVAL( TYPE_TCP ) }, LROT_NUMENTRY( TCP, TYPE_TCP )
{ LSTRKEY( "UDP" ), LNUMVAL( TYPE_UDP ) }, LROT_NUMENTRY( UDP, TYPE_UDP )
{ LSTRKEY( "__metatable" ), LROVAL( net_map ) }, LROT_TABENTRY( __metatable, net )
{ LNILKEY, LNILVAL } LROT_END( net, net, 0 )
};
int luaopen_net( lua_State *L ) { int luaopen_net( lua_State *L ) {
igmp_init(); igmp_init();
luaL_rometatable(L, NET_TABLE_TCP_SERVER, (void *)net_tcpserver_map); luaL_rometatable(L, NET_TABLE_TCP_SERVER, LROT_TABLEREF(net_tcpserver));
luaL_rometatable(L, NET_TABLE_TCP_CLIENT, (void *)net_tcpsocket_map); luaL_rometatable(L, NET_TABLE_TCP_CLIENT, LROT_TABLEREF(net_tcpsocket));
luaL_rometatable(L, NET_TABLE_UDP_SOCKET, (void *)net_udpsocket_map); luaL_rometatable(L, NET_TABLE_UDP_SOCKET, LROT_TABLEREF(net_udpsocket));
return 0; return 0;
} }
NODEMCU_MODULE(NET, "net", net_map, luaopen_net); NODEMCU_MODULE(NET, "net", net, luaopen_net);
// Module for interfacing with system // Module for interfacing with system
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
...@@ -16,12 +15,9 @@ ...@@ -16,12 +15,9 @@
#include "lundump.h" #include "lundump.h"
#include "platform.h" #include "platform.h"
#include "lrodefs.h"
#ifdef LUA_FLASH_STORE
#include "lflash.h" #include "lflash.h"
#endif #include <stdint.h>
#include "c_types.h" #include <string.h>
#include "c_string.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "user_interface.h" #include "user_interface.h"
#include "flash_api.h" #include "flash_api.h"
...@@ -124,6 +120,60 @@ static int node_sleep( lua_State* L ) ...@@ -124,6 +120,60 @@ static int node_sleep( lua_State* L )
#endif //PMSLEEP_ENABLE #endif //PMSLEEP_ENABLE
static int node_info( lua_State* L ) static int node_info( lua_State* L )
{ {
const char* options[] = {"hw", "sw_version", "build_config", "legacy", NULL};
int option = luaL_checkoption (L, 1, options[3], options);
switch (option) {
case 0: { // hw
lua_createtable (L, 0, 5);
int table_index = lua_gettop(L);
lua_pushinteger(L, system_get_chip_id()); // chip id
lua_setfield(L, table_index, "chip_id");
lua_pushinteger(L, spi_flash_get_id()); // flash id
lua_setfield(L, table_index, "flash_id");
lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB
lua_setfield(L, table_index, "flash_size");
lua_pushinteger(L, flash_rom_get_mode());
lua_setfield(L, table_index, "flash_mode");
lua_pushinteger(L, flash_rom_get_speed());
lua_setfield(L, table_index, "flash_speed");
return 1;
}
case 1: { // sw_version
lua_createtable (L, 0, 7);
int table_index = lua_gettop(L);
lua_pushinteger(L, NODE_VERSION_MAJOR);
lua_setfield(L, table_index, "node_version_major");
lua_pushinteger(L, NODE_VERSION_MINOR);
lua_setfield(L, table_index, "node_version_minor");
lua_pushinteger(L, NODE_VERSION_REVISION);
lua_setfield(L, table_index, "node_version_revision");
lua_pushstring(L, BUILDINFO_BRANCH);
lua_setfield(L, table_index, "git_branch");
lua_pushstring(L, BUILDINFO_COMMIT_ID);
lua_setfield(L, table_index, "git_commit_id");
lua_pushstring(L, BUILDINFO_RELEASE);
lua_setfield(L, table_index, "git_release");
lua_pushstring(L, BUILDINFO_RELEASE_DTS);
lua_setfield(L, table_index, "git_commit_dts");
return 1;
}
case 2: { // build_config
lua_createtable (L, 0, 4);
int table_index = lua_gettop(L);
lua_pushboolean(L, BUILDINFO_SSL);
lua_setfield(L, table_index, "ssl");
lua_pushnumber(L, BUILDINFO_LFS);
lua_setfield(L, table_index, "lfs_size");
lua_pushstring(L, BUILDINFO_MODULES);
lua_setfield(L, table_index, "modules");
lua_pushstring(L, BUILDINFO_BUILD_TYPE);
lua_setfield(L, table_index, "number_type");
return 1;
}
default:
{
platform_print_deprecation_note("node.info() without parameter", "in the next version");
lua_pushinteger(L, NODE_VERSION_MAJOR); lua_pushinteger(L, NODE_VERSION_MAJOR);
lua_pushinteger(L, NODE_VERSION_MINOR); lua_pushinteger(L, NODE_VERSION_MINOR);
lua_pushinteger(L, NODE_VERSION_REVISION); lua_pushinteger(L, NODE_VERSION_REVISION);
...@@ -133,6 +183,8 @@ static int node_info( lua_State* L ) ...@@ -133,6 +183,8 @@ static int node_info( lua_State* L )
lua_pushinteger(L, flash_rom_get_mode()); lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed()); lua_pushinteger(L, flash_rom_get_speed());
return 8; return 8;
}
}
} }
// Lua: chipid() // Lua: chipid()
...@@ -162,10 +214,6 @@ static int node_flashid( lua_State* L ) ...@@ -162,10 +214,6 @@ static int node_flashid( lua_State* L )
// Lua: flashsize() // Lua: flashsize()
static int node_flashsize( lua_State* L ) static int node_flashsize( lua_State* L )
{ {
if (lua_type(L, 1) == LUA_TNUMBER)
{
flash_rom_set_size_byte(luaL_checkinteger(L, 1));
}
uint32_t sz = flash_rom_get_size_byte(); uint32_t sz = flash_rom_get_size_byte();
lua_pushinteger( L, sz ); lua_pushinteger( L, sz );
return 1; return 1;
...@@ -197,7 +245,7 @@ static int output_redir_ref = LUA_NOREF; ...@@ -197,7 +245,7 @@ static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1; static int serial_debug = 1;
void output_redirect(const char *str) { void output_redirect(const char *str) {
lua_State *L = lua_getstate(); lua_State *L = lua_getstate();
// if(c_strlen(str)>=TX_BUFF_SIZE){ // if(strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n"); // NODE_ERR("output too long.\n");
// return; // return;
// } // }
...@@ -268,18 +316,18 @@ static int node_compile( lua_State* L ) ...@@ -268,18 +316,18 @@ static int node_compile( 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 );
const char *basename = vfs_basename( fname ); const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid"); luaL_argcheck(L, strlen(basename) <= FS_OBJ_NAME_LEN && strlen(fname) == len, 1, "filename invalid");
char *output = luaM_malloc( L, len+1 ); char *output = luaM_malloc( L, len+1 );
c_strcpy(output, fname); 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 || (strcmp( output + len - 4, ".lua") != 0) ) {
luaM_free( L, output ); 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[strlen(output) - 2] = 'c';
output[c_strlen(output) - 1] = '\0'; output[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) {
...@@ -578,68 +626,241 @@ static int node_random (lua_State *L) { ...@@ -578,68 +626,241 @@ static int node_random (lua_State *L) {
return 1; return 1;
} }
#ifdef DEVELOPMENT_TOOLS
// Lua: rec = node.readrcr(id)
static int node_readrcr (lua_State *L) {
int id = luaL_checkinteger(L, 1);
char *data;
int n = platform_rcr_read(id, (void **)&data);
if (n == ~0) return 0;
lua_pushlstring(L, data, n);
return 1;
}
// Lua: n = node.writercr(id,rec)
static int node_writercr (lua_State *L) {
int id = luaL_checkinteger(L, 1),l;
const char *data = lua_tolstring(L, 2, &l);
int n = platform_rcr_write(id, data, l);
lua_pushinteger(L, n);
return 1;
}
#endif
typedef enum pt_t { lfs_addr=0, lfs_size, spiffs_addr, spiffs_size, max_pt} pt_t;
LROT_BEGIN(pt)
LROT_NUMENTRY( lfs_addr, lfs_addr )
LROT_NUMENTRY( lfs_size, lfs_size )
LROT_NUMENTRY( spiffs_addr, spiffs_addr )
LROT_NUMENTRY( spiffs_size, spiffs_size )
LROT_END( pt, NULL, 0 )
// Lua: ptinfo = node.getpartitiontable()
static int node_getpartitiontable (lua_State *L) {
uint32_t param[max_pt] = {0};
param[lfs_size] = platform_flash_get_partition(NODEMCU_LFS0_PARTITION, param + lfs_addr);
param[spiffs_size] = platform_flash_get_partition(NODEMCU_SPIFFS0_PARTITION, param + spiffs_addr);
lua_settop(L, 0);
lua_createtable (L, 0, max_pt); /* at index 1 */
lua_pushrotable(L, (void*)pt_map); /* at index 2 */
lua_pushnil(L); /* first key at index 3 */
while (lua_next(L, 2) != 0) { /* key at index 3, and v at index 4 */
lua_pushvalue(L, 3); /* dup key to index 5 */
lua_pushinteger(L, param[lua_tointeger(L, 4)]); /* param [v] at index 6 */
lua_rawset(L, 1);
lua_pop(L, 1); /* discard v */
}
lua_pop(L, 1); /* discard pt_map reference */
return 1;
}
static void insert_partition(partition_item_t *p, int n, uint32_t type, uint32_t addr) {
if (n>0)
memmove(p+1, p, n*sizeof(partition_item_t)); /* overlapped so must be move not cpy */
p->type = type;
p->addr = addr;
p->size = 0;
}
static void delete_partition(partition_item_t *p, int n) {
if (n>0)
memmove(p, p+1, n*sizeof(partition_item_t)); /* overlapped so must be move not cpy */
}
#define SKIP (~0)
#define IROM0_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_IROM0TEXT_PARTITION)
#define LFS_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_LFS0_PARTITION)
#define SPIFFS_PARTITION (SYSTEM_PARTITION_CUSTOMER_BEGIN + NODEMCU_SPIFFS0_PARTITION)
// Lua: node.setpartitiontable(pt_settings)
static int node_setpartitiontable (lua_State *L) {
partition_item_t *rcr_pt = NULL, *pt;
uint32_t flash_size = flash_rom_get_size_byte();
uint32_t i = platform_rcr_read(PLATFORM_RCR_PT, (void **) &rcr_pt);
uint32_t last = 0;
uint32_t n = i / sizeof(partition_item_t);
uint32_t param[max_pt] = {SKIP, SKIP, SKIP, SKIP};
luaL_argcheck(L, lua_istable(L, 1), 1, "must be table");
lua_settop(L, 1);
/* convert input table into 4 option array */
lua_pushrotable(L, (void*)pt_map); /* at index 2 */
lua_pushnil(L); /* first key at index 3 */
while (lua_next(L, 1) != 0) {
/* 'key' (at index 3) and 'value' (at index 4) */
luaL_argcheck(L, lua_isstring(L, 3) && lua_isnumber(L, 4), 1, "invalid partition setting");
lua_pushvalue(L, 3); /* dup key to index 5 */
lua_rawget(L, 2); /* lookup in pt_map */
luaL_argcheck(L, !lua_isnil(L, -1), 1, "invalid partition setting");
param[lua_tointeger(L, 5)] = lua_tointeger(L, 4);
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 2); /* discard value and lookup */
}
/*
* Allocate a scratch Partition Table as userdata on the Lua stack, and copy the
* current Flash PT into this for manipulation
*/
lua_newuserdata(L, (n+2)*sizeof(partition_item_t));
pt = lua_touserdata (L, -1);
memcpy(pt, rcr_pt, n*sizeof(partition_item_t));
pt[n].type = 0; pt[n+1].type = 0;
for (i = 0; i < n; i ++) {
partition_item_t *p = pt + i;
if (p->type == IROM0_PARTITION && p[1].type != LFS_PARTITION) {
// if the LFS partition is not following IROM0 then slot a blank one in
insert_partition(p + 1, n-i-1, LFS_PARTITION, p->addr + p->size);
n++;
} else if (p->type == LFS_PARTITION) {
if (p[1].type != SPIFFS_PARTITION) {
// if the SPIFFS partition is not following LFS then slot a blank one in
insert_partition(p + 1, n-i-1, SPIFFS_PARTITION, 0);
n++;
}
// update the LFS options if set
if (param[lfs_addr] != SKIP) {
p->addr = param[lfs_addr];
}
if (param[lfs_size] != SKIP) {
p->size = param[lfs_size];
}
} else if (p->type == SPIFFS_PARTITION) {
// update the SPIFFS options if set
if (param[spiffs_addr] != SKIP) {
p->addr = param[spiffs_addr];
p->size = SKIP;
}
if (param[spiffs_size] != SKIP) {
// BOTCH: - at the moment the firmware doesn't boot if the SPIFFS partition
// is deleted so the minimum SPIFFS size is 64Kb
p->size = param[spiffs_size] > 0x10000 ? param[spiffs_size] : 0x10000;
}
if (p->size == SKIP) {
if (p->addr < 0) {
// This allocate all the remaining flash to SPIFFS
p->addr = last;
p->size = flash_size - last;
} else {
p->size = flash_size - p->addr;
}
} else if (/* size is specified && */ p->addr == 0) {
// if the is addr not specified then start SPIFFS at 1Mb
// boundary if the size will fit otherwise make it consecutive
// to the previous partition.
p->addr = (p->size <= flash_size - 0x100000) ? 0x100000 : last;
}
}
if (p->size == 0) {
// Delete 0-sized partitions as the SDK barfs on these
delete_partition(p, n-i-1);
n--; i--;
} else {
// Do consistency tests on the partition
if (p->addr & (INTERNAL_FLASH_SECTOR_SIZE - 1) ||
p->size & (INTERNAL_FLASH_SECTOR_SIZE - 1) ||
p->addr < last ||
p->addr + p->size > flash_size) {
luaL_error(L, "value out of range");
}
}
}
// for (i = 0; i < n; i ++)
// dbg_printf("Partition %d: %04x %06x %06x\n", i, pt[i].type, pt[i].addr, pt[i].size);
platform_rcr_write(PLATFORM_RCR_PT, pt, n*sizeof(partition_item_t));
while(1); // Trigger WDT; the new PT will be loaded on reboot
return 0;
}
// Module function map // Module function map
static const LUA_REG_TYPE node_egc_map[] = { LROT_BEGIN(node_egc)
{ LSTRKEY( "meminfo" ), LFUNCVAL( node_egc_meminfo ) }, LROT_FUNCENTRY( meminfo, node_egc_meminfo )
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) }, LROT_FUNCENTRY( setmode, node_egc_setmode )
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) }, LROT_NUMENTRY( NOT_ACTIVE, EGC_NOT_ACTIVE )
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) }, LROT_NUMENTRY( ON_ALLOC_FAILURE, EGC_ON_ALLOC_FAILURE )
{ LSTRKEY( "ON_MEM_LIMIT" ), LNUMVAL( EGC_ON_MEM_LIMIT ) }, LROT_NUMENTRY( ON_MEM_LIMIT, EGC_ON_MEM_LIMIT )
{ LSTRKEY( "ALWAYS" ), LNUMVAL( EGC_ALWAYS ) }, LROT_NUMENTRY( ALWAYS, EGC_ALWAYS )
{ LNILKEY, LNILVAL } LROT_END( node_egc, NULL, 0 )
};
static const LUA_REG_TYPE node_task_map[] = { LROT_BEGIN(node_task)
{ LSTRKEY( "post" ), LFUNCVAL( node_task_post ) }, LROT_FUNCENTRY( post, node_task_post )
{ LSTRKEY( "LOW_PRIORITY" ), LNUMVAL( TASK_PRIORITY_LOW ) }, LROT_NUMENTRY( LOW_PRIORITY, TASK_PRIORITY_LOW )
{ LSTRKEY( "MEDIUM_PRIORITY" ), LNUMVAL( TASK_PRIORITY_MEDIUM ) }, LROT_NUMENTRY( MEDIUM_PRIORITY, TASK_PRIORITY_MEDIUM )
{ LSTRKEY( "HIGH_PRIORITY" ), LNUMVAL( TASK_PRIORITY_HIGH ) }, LROT_NUMENTRY( HIGH_PRIORITY, TASK_PRIORITY_HIGH )
{ LNILKEY, LNILVAL } LROT_END( node_task, NULL, 0 )
};
LROT_BEGIN(node)
static const LUA_REG_TYPE node_map[] = LROT_FUNCENTRY( heap, node_heap )
{ LROT_FUNCENTRY( info, node_info )
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) }, LROT_TABENTRY( task, node_task )
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) }, LROT_FUNCENTRY( flashreload, luaN_reload_reboot )
{ LSTRKEY( "task" ), LROVAL( node_task_map ) }, LROT_FUNCENTRY( flashindex, luaN_index )
#ifdef LUA_FLASH_STORE LROT_FUNCENTRY( restart, node_restart )
{ LSTRKEY( "flashreload" ), LFUNCVAL( luaN_reload_reboot ) }, LROT_FUNCENTRY( dsleep, node_deepsleep )
{ LSTRKEY( "flashindex" ), LFUNCVAL( luaN_index ) }, LROT_FUNCENTRY( dsleepMax, dsleepMax )
#endif LROT_FUNCENTRY( sleep, node_sleep )
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
{ LSTRKEY( "dsleepMax" ), LFUNCVAL( dsleepMax ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( node_sleep ) },
#ifdef PMSLEEP_ENABLE #ifdef PMSLEEP_ENABLE
PMSLEEP_INT_MAP, PMSLEEP_INT_MAP
#endif #endif
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) }, #ifdef DEVELOPMENT_TOOLS
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) }, LROT_FUNCENTRY( readrcr, node_readrcr )
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) }, LROT_FUNCENTRY( writercr, node_writercr )
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) }, #endif
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) }, LROT_FUNCENTRY( chipid, node_chipid )
LROT_FUNCENTRY( flashid, node_flashid )
LROT_FUNCENTRY( flashsize, node_flashsize )
LROT_FUNCENTRY( input, node_input )
LROT_FUNCENTRY( output, node_output )
// Moved to adc module, use adc.readvdd33() // Moved to adc module, use adc.readvdd33()
// { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) }, // LROT_FUNCENTRY( readvdd33, node_readvdd33 )
{ LSTRKEY( "compile" ), LFUNCVAL( node_compile) }, LROT_FUNCENTRY( compile, node_compile )
{ LSTRKEY( "CPU80MHZ" ), LNUMVAL( CPU80MHZ ) }, LROT_NUMENTRY( CPU80MHZ, CPU80MHZ )
{ LSTRKEY( "CPU160MHZ" ), LNUMVAL( CPU160MHZ ) }, LROT_NUMENTRY( CPU160MHZ, CPU160MHZ )
{ LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) }, LROT_FUNCENTRY( setcpufreq, node_setcpufreq )
{ LSTRKEY( "getcpufreq" ), LFUNCVAL( node_getcpufreq) }, LROT_FUNCENTRY( getcpufreq, node_getcpufreq )
{ LSTRKEY( "bootreason" ), LFUNCVAL( node_bootreason) }, LROT_FUNCENTRY( bootreason, node_bootreason )
{ LSTRKEY( "restore" ), LFUNCVAL( node_restore) }, LROT_FUNCENTRY( restore, node_restore )
{ LSTRKEY( "random" ), LFUNCVAL( node_random) }, LROT_FUNCENTRY( random, node_random )
#ifdef LUA_OPTIMIZE_DEBUG #ifdef LUA_OPTIMIZE_DEBUG
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) }, LROT_FUNCENTRY( stripdebug, node_stripdebug )
#endif #endif
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) }, LROT_TABENTRY( egc, node_egc )
#ifdef DEVELOPMENT_TOOLS #ifdef DEVELOPMENT_TOOLS
{ LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) }, LROT_FUNCENTRY( osprint, node_osprint )
#endif #endif
LROT_FUNCENTRY( getpartitiontable, node_getpartitiontable )
LROT_FUNCENTRY( setpartitiontable, node_setpartitiontable )
// Combined to dsleep(us, option) // Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) }, // LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption )
{ LNILKEY, LNILVAL } LROT_END( node, NULL, 0 )
};
NODEMCU_MODULE(NODE, "node", node_map, NULL); NODEMCU_MODULE(NODE, "node", node, NULL);
...@@ -282,29 +282,29 @@ static int ow_crc16( lua_State *L ) ...@@ -282,29 +282,29 @@ static int ow_crc16( lua_State *L )
#endif #endif
// Module function map // Module function map
static const LUA_REG_TYPE ow_map[] = { LROT_BEGIN(ow)
{ LSTRKEY( "setup" ), LFUNCVAL( ow_setup ) }, LROT_FUNCENTRY( setup, ow_setup )
{ LSTRKEY( "reset" ), LFUNCVAL( ow_reset ) }, LROT_FUNCENTRY( reset, ow_reset )
{ LSTRKEY( "skip" ), LFUNCVAL( ow_skip ) }, LROT_FUNCENTRY( skip, ow_skip )
{ LSTRKEY( "select" ), LFUNCVAL( ow_select ) }, LROT_FUNCENTRY( select, ow_select )
{ LSTRKEY( "write" ), LFUNCVAL( ow_write ) }, LROT_FUNCENTRY( write, ow_write )
{ LSTRKEY( "write_bytes" ), LFUNCVAL( ow_write_bytes ) }, LROT_FUNCENTRY( write_bytes, ow_write_bytes )
{ LSTRKEY( "read" ), LFUNCVAL( ow_read ) }, LROT_FUNCENTRY( read, ow_read )
{ LSTRKEY( "read_bytes" ), LFUNCVAL( ow_read_bytes ) }, LROT_FUNCENTRY( read_bytes, ow_read_bytes )
{ LSTRKEY( "depower" ), LFUNCVAL( ow_depower ) }, LROT_FUNCENTRY( depower, ow_depower )
#if ONEWIRE_SEARCH #if ONEWIRE_SEARCH
{ LSTRKEY( "reset_search" ), LFUNCVAL( ow_reset_search ) }, LROT_FUNCENTRY( reset_search, ow_reset_search )
{ LSTRKEY( "target_search" ), LFUNCVAL( ow_target_search ) }, LROT_FUNCENTRY( target_search, ow_target_search )
{ LSTRKEY( "search" ), LFUNCVAL( ow_search ) }, LROT_FUNCENTRY( search, ow_search )
#endif #endif
#if ONEWIRE_CRC #if ONEWIRE_CRC
{ LSTRKEY( "crc8" ), LFUNCVAL( ow_crc8 ) }, LROT_FUNCENTRY( crc8, ow_crc8 )
#if ONEWIRE_CRC16 #if ONEWIRE_CRC16
{ LSTRKEY( "check_crc16" ), LFUNCVAL( ow_check_crc16 ) }, LROT_FUNCENTRY( check_crc16, ow_check_crc16 )
{ LSTRKEY( "crc16" ), LFUNCVAL( ow_crc16 ) }, LROT_FUNCENTRY( crc16, ow_crc16 )
#endif #endif
#endif #endif
{ LNILKEY, LNILVAL } LROT_END( ow, NULL, 0 )
};
NODEMCU_MODULE(OW, "ow", ow_map, NULL);
NODEMCU_MODULE(OW, "ow", ow, NULL);
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "task/task.h" #include "task/task.h"
#include "c_string.h" #include <string.h>
#include "c_stdlib.h" #include <stdlib.h>
#include "pcm.h" #include "pcm/pcm.h"
#include "pcm_drv.h" #include "pcm/pcm_drv.h"
#define GET_PUD() pud_t *pud = (pud_t *)luaL_checkudata(L, 1, "pcm.driver"); \ #define GET_PUD() pud_t *pud = (pud_t *)luaL_checkudata(L, 1, "pcm.driver"); \
...@@ -43,11 +43,11 @@ static int pcm_drv_free( lua_State *L ) ...@@ -43,11 +43,11 @@ static int pcm_drv_free( lua_State *L )
UNREF_CB( cfg->self_ref ); UNREF_CB( cfg->self_ref );
if (cfg->bufs[0].data) { if (cfg->bufs[0].data) {
c_free( cfg->bufs[0].data ); free( cfg->bufs[0].data );
cfg->bufs[0].data = NULL; cfg->bufs[0].data = NULL;
} }
if (cfg->bufs[1].data) { if (cfg->bufs[1].data) {
c_free( cfg->bufs[1].data ); free( cfg->bufs[1].data );
cfg->bufs[1].data = NULL; cfg->bufs[1].data = NULL;
} }
...@@ -152,19 +152,19 @@ static int pcm_drv_on( lua_State *L ) ...@@ -152,19 +152,19 @@ static int pcm_drv_on( lua_State *L )
is_func = TRUE; is_func = TRUE;
} }
if ((len == 4) && (c_strcmp( event, "data" ) == 0)) { if ((len == 4) && (strcmp( event, "data" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_data_ref); luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_data_ref);
cfg->cb_data_ref = COND_REF( is_func ); cfg->cb_data_ref = COND_REF( is_func );
} else if ((len == 7) && (c_strcmp( event, "drained" ) == 0)) { } else if ((len == 7) && (strcmp( event, "drained" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_drained_ref); luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_drained_ref);
cfg->cb_drained_ref = COND_REF( is_func ); cfg->cb_drained_ref = COND_REF( is_func );
} else if ((len == 6) && (c_strcmp( event, "paused" ) == 0)) { } else if ((len == 6) && (strcmp( event, "paused" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_paused_ref); luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_paused_ref);
cfg->cb_paused_ref = COND_REF( is_func ); cfg->cb_paused_ref = COND_REF( is_func );
} else if ((len == 7) && (c_strcmp( event, "stopped" ) == 0)) { } else if ((len == 7) && (strcmp( event, "stopped" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_stopped_ref); luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_stopped_ref);
cfg->cb_stopped_ref = COND_REF( is_func ); cfg->cb_stopped_ref = COND_REF( is_func );
} else if ((len == 2) && (c_strcmp( event, "vu" ) == 0)) { } else if ((len == 2) && (strcmp( event, "vu" ) == 0)) {
luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_vu_ref); luaL_unref( L, LUA_REGISTRYINDEX, cfg->cb_vu_ref);
cfg->cb_vu_ref = COND_REF( is_func ); cfg->cb_vu_ref = COND_REF( is_func );
...@@ -229,34 +229,34 @@ static int pcm_new( lua_State *L ) ...@@ -229,34 +229,34 @@ static int pcm_new( lua_State *L )
} }
static const LUA_REG_TYPE pcm_driver_map[] = { LROT_BEGIN(pcm_driver)
{ LSTRKEY( "play" ), LFUNCVAL( pcm_drv_play ) }, LROT_FUNCENTRY( play, pcm_drv_play )
{ LSTRKEY( "pause" ), LFUNCVAL( pcm_drv_pause ) }, LROT_FUNCENTRY( pause, pcm_drv_pause )
{ LSTRKEY( "stop" ), LFUNCVAL( pcm_drv_stop ) }, LROT_FUNCENTRY( stop, pcm_drv_stop )
{ LSTRKEY( "close" ), LFUNCVAL( pcm_drv_close ) }, LROT_FUNCENTRY( close, pcm_drv_close )
{ LSTRKEY( "on" ), LFUNCVAL( pcm_drv_on ) }, LROT_FUNCENTRY( on, pcm_drv_on )
{ LSTRKEY( "__gc" ), LFUNCVAL( pcm_drv_free ) }, LROT_FUNCENTRY( __gc, pcm_drv_free )
{ LSTRKEY( "__index" ), LROVAL( pcm_driver_map ) }, LROT_TABENTRY( __index, pcm_driver )
{ LNILKEY, LNILVAL } LROT_END( pcm_driver, pcm_driver, LROT_MASK_GC_INDEX )
};
// Module function map // Module function map
static const LUA_REG_TYPE pcm_map[] = { LROT_BEGIN(pcm)
{ LSTRKEY( "new" ), LFUNCVAL( pcm_new ) }, LROT_FUNCENTRY( new, pcm_new )
{ LSTRKEY( "SD" ), LNUMVAL( PCM_DRIVER_SD ) }, LROT_NUMENTRY( SD, PCM_DRIVER_SD )
{ LSTRKEY( "RATE_1K" ), LNUMVAL( PCM_RATE_1K ) }, LROT_NUMENTRY( RATE_1K, PCM_RATE_1K )
{ LSTRKEY( "RATE_2K" ), LNUMVAL( PCM_RATE_2K ) }, LROT_NUMENTRY( RATE_2K, PCM_RATE_2K )
{ LSTRKEY( "RATE_4K" ), LNUMVAL( PCM_RATE_4K ) }, LROT_NUMENTRY( RATE_4K, PCM_RATE_4K )
{ LSTRKEY( "RATE_5K" ), LNUMVAL( PCM_RATE_5K ) }, LROT_NUMENTRY( RATE_5K, PCM_RATE_5K )
{ LSTRKEY( "RATE_8K" ), LNUMVAL( PCM_RATE_8K ) }, LROT_NUMENTRY( RATE_8K, PCM_RATE_8K )
{ LSTRKEY( "RATE_10K" ), LNUMVAL( PCM_RATE_10K ) }, LROT_NUMENTRY( RATE_10K, PCM_RATE_10K )
{ LSTRKEY( "RATE_12K" ), LNUMVAL( PCM_RATE_12K ) }, LROT_NUMENTRY( RATE_12K, PCM_RATE_12K )
{ LSTRKEY( "RATE_16K" ), LNUMVAL( PCM_RATE_16K ) }, LROT_NUMENTRY( RATE_16K, PCM_RATE_16K )
{ LNILKEY, LNILVAL } LROT_END( pcm, NULL, 0 )
};
int luaopen_pcm( lua_State *L ) { int luaopen_pcm( lua_State *L ) {
luaL_rometatable( L, "pcm.driver", (void *)pcm_driver_map ); // create metatable luaL_rometatable( L, "pcm.driver", LROT_TABLEREF(pcm_driver));
pcm_data_vu_task = task_get_id( pcm_data_vu ); pcm_data_vu_task = task_get_id( pcm_data_vu );
pcm_data_play_task = task_get_id( pcm_data_play ); pcm_data_play_task = task_get_id( pcm_data_play );
...@@ -264,4 +264,4 @@ int luaopen_pcm( lua_State *L ) { ...@@ -264,4 +264,4 @@ int luaopen_pcm( lua_State *L ) {
return 0; return 0;
} }
NODEMCU_MODULE(PCM, "pcm", pcm_map, luaopen_pcm); NODEMCU_MODULE(PCM, "pcm", pcm, luaopen_pcm);
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "ets_sys.h" #include "ets_sys.h"
#include "os_type.h" #include "os_type.h"
#include "osapi.h" #include "osapi.h"
#include "c_stdlib.h" #include <stdlib.h>
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
...@@ -135,10 +135,10 @@ static int perf_stop(lua_State *L) ...@@ -135,10 +135,10 @@ static int perf_stop(lua_State *L)
return 4; return 4;
} }
static const LUA_REG_TYPE perf_map[] = { LROT_BEGIN(perf)
{ LSTRKEY( "start" ), LFUNCVAL( perf_start ) }, LROT_FUNCENTRY( start, perf_start )
{ LSTRKEY( "stop" ), LFUNCVAL( perf_stop ) }, LROT_FUNCENTRY( stop, perf_stop )
{ LNILKEY, LNILVAL } LROT_END( perf, NULL, 0 )
};
NODEMCU_MODULE(PERF, "perf", perf_map, NULL);
NODEMCU_MODULE(PERF, "perf", perf, NULL);
/*
** The pipe algo is somewhat similar to the luaL_Buffer algo, except that it uses
** table to store the LUAL_BUFFERSIZE byte array chunks instead of the stack.
** Writing is always to the last UD in the table and overflow pushes a new UD to
** the end of the table. Reading is always from the first UD in the table and
** underrun removes the first UD to shift a new one into slot 1.
**
** Reads and writes may span multiple UD buffers and if the read spans multiple UDs
** then the parts are collected as strings on the Lua stack and then concatenated
** with a `lua_concat()`.
**
** Note that pipes also support the undocumented length and tostring operators
** for debugging puposes, so if p is a pipe then #p[1] gives the effective
** length of pipe slot 1 and printing p[1] gives its contents
**
** Read the docs/modules/pipe.md documentation for a functional description.
*/
#include "module.h"
#include "lauxlib.h"
#include <string.h>
#define INVALID_LEN ((unsigned)-1)
#define LUA_USE_MODULES_PIPE
typedef struct buffer {
int start, end;
char buf[LUAL_BUFFERSIZE];
} buffer_t;
LROT_TABLE(pipe_meta)
/* Validation and utility functions */
#define AT_HEAD 1
#define AT_TAIL 0
static buffer_t *checkPipeUD (lua_State *L, int ndx) { // [-0, +0, v]
buffer_t *ud = lua_touserdata(L, ndx);
if (ud && lua_getmetatable(L, ndx)) { /* Get UD and its metatable? */
lua_pushrotable(L, LROT_TABLEREF(pipe_meta)); /* push correct metatable */
if (lua_rawequal(L, -1, -2)) { /* Do these match? */
lua_pop(L, 2); /* remove both metatables */
return ud; /* and return ptr to buffer_t rec */
}
}
if (!lua_istable(L,ndx))
luaL_typerror(L, ndx, "pipeUD"); /* NORETURN error */
return NULL; /* keep compiler happy */
}
static buffer_t *newPipeUD(lua_State *L, int ndx, int n) { // [-0,+0,-]
buffer_t *ud = (buffer_t *) lua_newuserdata(L, sizeof(buffer_t));
lua_pushrotable(L, LROT_TABLEREF(pipe_meta)); /* push the metatable */
lua_setmetatable(L, -2); /* set UD's metabtable to pipe_meta */
ud->start = ud->end = 0;
lua_rawseti(L, ndx, n); /* T[#T+1] = new UD */
return ud; /* ud points to new T[#T] */
}
static buffer_t *checkPipeTable (lua_State *L, int tbl, int head) {//[-0, +0, v]
int m = lua_gettop(L), n = lua_objlen(L, tbl);
if (lua_type(L, tbl) == LUA_TTABLE && lua_getmetatable(L, tbl)) {
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));/* push comparison metatable */
if (lua_rawequal(L, -1, -2)) { /* check these match */
buffer_t *ud;
if (n == 0) {
ud = head ? NULL : newPipeUD(L, tbl, 1);
} else {
int i = head ? 1 : n; /* point to head or tail of T */
lua_rawgeti(L, tbl, i); /* and fetch UD */
ud = checkPipeUD(L, -1);
}
lua_settop(L, m);
return ud; /* and return ptr to buffer_t rec */
}
}
luaL_typerror(L, tbl, "pipe table");
return NULL; /* NORETURN avoid compiler error */
}
#define CHAR_DELIM -1
#define CHAR_DELIM_KEEP -2
static char getsize_delim (lua_State *L, int ndx, int *len) { // [-0, +0, v]
char delim;
int n;
if( lua_type( L, ndx ) == LUA_TNUMBER ) {
n = luaL_checkinteger( L, ndx );
luaL_argcheck(L, n > 0, ndx, "invalid chunk size");
delim = '\0';
} else if (lua_isnil(L, ndx)) {
n = CHAR_DELIM;
delim = '\n';
} else {
size_t ldelim;
const char *s = lua_tolstring( L, 2, &ldelim);
n = ldelim == 2 && s[1] == '+' ? CHAR_DELIM_KEEP : CHAR_DELIM ;
luaL_argcheck(L, ldelim + n == 0, ndx, "invalid delimiter");
delim = s[0];
}
if (len)
*len = n;
return delim;
}
/* Lua callable methods */
//Lua s = pipeUD:tostring()
static int pipe__tostring (lua_State *L) {
if (lua_type(L, 1) == LUA_TTABLE) {
lua_pushfstring(L, "Pipe: %p", lua_topointer(L, 1));
} else {
buffer_t *ud = checkPipeUD(L, 1);
lua_pushlstring(L, ud->buf + ud->start, ud->end - ud->start);
}
return 1;
}
// len = #pipeobj[1]
static int pipe__len (lua_State *L) {
if (lua_type(L, 1) == LUA_TTABLE) {
lua_pushinteger(L, lua_objlen(L, 1));
} else {
buffer_t *ud = checkPipeUD(L, 1);
lua_pushinteger(L, ud->end - ud->start);
}
return 1;
}
// Lua: buf = pipe.create()
static int pipe_create(lua_State *L) {
lua_createtable (L, 1, 0);
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));
lua_setmetatable(L, 1); /* set table's metabtable to pipe_meta */
return 1; /* return the table */
}
// Lua: rec = p:read(end_or_delim) // also [-2, +1,- ]
static int pipe_read(lua_State *L) {
buffer_t *ud = checkPipeTable(L, 1, AT_HEAD);
int i, k=0, n;
lua_settop(L,2);
const char delim = getsize_delim(L, 2, &n);
lua_pop(L,1);
while (ud && n) {
int want, used, avail = ud->end - ud->start;
if (n < 0 /* one of the CHAR_DELIM flags */) {
/* getting a delimited chunk so scan for delimiter */
for (i = ud->start; i < ud->end && ud->buf[i] != delim; i++) {}
/* Can't have i = ud->end and ud->buf[i] == delim so either */
/* we've scanned full buffer avail OR we've hit a delim char */
if (i == ud->end) {
want = used = avail; /* case where we've scanned without a hit */
} else {
want = used = i + 1 - ud->start; /* case where we've hit a delim */
if (n == CHAR_DELIM)
want--;
}
} else {
want = used = (n < avail) ? n : avail;
n -= used;
}
lua_pushlstring(L, ud->buf + ud->start, want); /* part we want */
k++;
ud->start += used;
if (ud->start == ud->end) {
/* shift the pipe array down overwriting T[1] */
int nUD = lua_objlen(L, 1);
for (i = 1; i < nUD; i++) { /* for i = 1, nUD-1 */
lua_rawgeti(L, 1, i+1); lua_rawseti(L, 1, i); /* T[i] = T[i+1] */
}
lua_pushnil(L); lua_rawseti(L, 1, nUD--); /* T[n] = nil */
if (nUD) {
lua_rawgeti(L, 1, 1);
ud = checkPipeUD(L, -1);
lua_pop(L, 1);
} else {
ud = NULL;
}
}
}
if (k)
lua_concat(L, k);
else
lua_pushnil(L);
return 1;
}
// Lua: buf:unread(some_string)
static int pipe_unread(lua_State *L) {
size_t l = INVALID_LEN;
const char *s = lua_tolstring(L, 2, &l);
if (l==0)
return 0;
luaL_argcheck(L, l != INVALID_LEN, 2, "must be a string");
buffer_t *ud = checkPipeTable(L, 1, AT_HEAD);
do {
int used = ud->end - ud->start, lrem = LUAL_BUFFERSIZE-used;
if (used == LUAL_BUFFERSIZE) {
int i, nUD = lua_objlen(L, 1);
for (i = nUD; i > 0; i--) { /* for i = nUD-1,1,-1 */
lua_rawgeti(L, 1, i); lua_rawseti(L, 1, i+1); /* T[i+1] = T[i] */
}
ud = newPipeUD(L, 1, 1);
used = 0; lrem = LUAL_BUFFERSIZE;
} else if (ud->end < LUAL_BUFFERSIZE) {
memmove(ud->buf + lrem,
ud->buf + ud->start, used); /* must be memmove not cpy */
}
ud->start = lrem; ud->end = LUAL_BUFFERSIZE;
if (l <= (unsigned )lrem)
break;
/* If we've got here then the remaining string is strictly longer than the */
/* remaining buffer space, so top off the buffer before looping around again */
l -= lrem;
memcpy(ud->buf, s + l, lrem);
ud->start = 0;
} while(1);
/* Copy any residual tail to the UD buffer. Note that this is l>0 and */
ud->start -= l;
memcpy(ud->buf + ud->start, s, l);
return 0;
}
// Lua: buf:write(some_string)
static int pipe_write(lua_State *L) {
size_t l = INVALID_LEN;
const char *s = lua_tolstring(L, 2, &l);
if (l==0)
return 0;
luaL_argcheck(L, l != INVALID_LEN, 2, "must be a string");
buffer_t *ud = checkPipeTable(L, 1, AT_TAIL);
do {
int used = ud->end - ud->start;
if (used == LUAL_BUFFERSIZE) {
ud = newPipeUD(L, 1, lua_objlen(L, 1)+1);
used = 0;
} else if (ud->start) {
memmove(ud->buf, ud->buf + ud->start, used); /* must be memmove not cpy */
ud->start = 0; ud->end = used;
}
int lrem = LUAL_BUFFERSIZE-used;
if (l <= (unsigned )lrem)
break;
/* If we've got here then the remaining string is longer than the buffer */
/* space left, so top off the buffer before looping around again */
memcpy(ud->buf + ud->end, s, lrem);
ud->end += lrem;
l -= lrem;
s += lrem;
} while(1);
/* Copy any residual tail to the UD buffer. Note that this is l>0 and */
memcpy(ud->buf + ud->end, s, l);
ud->end += l;
return 0;
}
// Lua: fread = pobj:reader(1400) -- or other number
// fread = pobj:reader('\n') -- or other delimiter (delim is stripped)
// fread = pobj:reader('\n+') -- or other delimiter (delim is retained)
#define TBL lua_upvalueindex(1)
#define N lua_upvalueindex(2)
static int pipe_read_aux(lua_State *L) {
lua_settop(L, 0); /* ignore args since we use upvals instead */
lua_pushvalue(L, TBL);
lua_pushvalue(L, N);
return pipe_read(L);
}
static int pipe_reader(lua_State *L) {
lua_settop(L,2);
checkPipeTable (L, 1,AT_HEAD);
getsize_delim(L, 2, NULL);
lua_pushcclosure(L, pipe_read_aux, 2); /* return (closure, nil, table) */
return 1;
}
LROT_BEGIN(pipe_meta)
LROT_TABENTRY( __index, pipe_meta)
LROT_FUNCENTRY( __len, pipe__len )
LROT_FUNCENTRY( __tostring, pipe__tostring )
LROT_FUNCENTRY( read, pipe_read )
LROT_FUNCENTRY( reader, pipe_reader )
LROT_FUNCENTRY( unread, pipe_unread )
LROT_FUNCENTRY( write, pipe_write )
LROT_END( pipe_meta, NULL, LROT_MASK_INDEX )
LROT_BEGIN(pipe)
LROT_FUNCENTRY( create, pipe_create )
LROT_END( lb, NULL, 0 )
NODEMCU_MODULE(PIPE, "pipe", pipe, NULL);
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "platform.h" #include "platform.h"
#include "c_types.h" #include <stdint.h>
// Lua: realfrequency = setup( id, frequency, duty ) // Lua: realfrequency = setup( id, frequency, duty )
static int lpwm_setup( lua_State* L ) static int lpwm_setup( lua_State* L )
...@@ -128,16 +128,16 @@ int lpwm_open( lua_State *L ) { ...@@ -128,16 +128,16 @@ int lpwm_open( lua_State *L ) {
} }
// Module function map // Module function map
static const LUA_REG_TYPE pwm_map[] = { LROT_BEGIN(pwm)
{ LSTRKEY( "setup" ), LFUNCVAL( lpwm_setup ) }, LROT_FUNCENTRY( setup, lpwm_setup )
{ LSTRKEY( "close" ), LFUNCVAL( lpwm_close ) }, LROT_FUNCENTRY( close, lpwm_close )
{ LSTRKEY( "start" ), LFUNCVAL( lpwm_start ) }, LROT_FUNCENTRY( start, lpwm_start )
{ LSTRKEY( "stop" ), LFUNCVAL( lpwm_stop ) }, LROT_FUNCENTRY( stop, lpwm_stop )
{ LSTRKEY( "setclock" ), LFUNCVAL( lpwm_setclock ) }, LROT_FUNCENTRY( setclock, lpwm_setclock )
{ LSTRKEY( "getclock" ), LFUNCVAL( lpwm_getclock ) }, LROT_FUNCENTRY( getclock, lpwm_getclock )
{ LSTRKEY( "setduty" ), LFUNCVAL( lpwm_setduty ) }, LROT_FUNCENTRY( setduty, lpwm_setduty )
{ LSTRKEY( "getduty" ), LFUNCVAL( lpwm_getduty ) }, LROT_FUNCENTRY( getduty, lpwm_getduty )
{ LNILKEY, LNILVAL } LROT_END( pwm, NULL, 0 )
};
NODEMCU_MODULE(PWM, "pwm", pwm_map, lpwm_open); NODEMCU_MODULE(PWM, "pwm", pwm, lpwm_open);
/*
* Software PWM using soft-interrupt timer1.
* Supports higher frequencies compared to Espressif provided one.
*
* Nikolay Fiykov
*/
// Module for interfacing with PWM2 driver
#include <stdint.h>
#include "lauxlib.h"
#include "module.h"
#include "driver/pwm2.h"
#define luaL_argcheck2(L, cond, numarg, extramsg) \
if (!(cond)) return luaL_argerror(L, (numarg), (extramsg))
//############################
// lua bindings
static int lpwm2_open(lua_State *L) {
pwm2_init();
return 0;
}
static int lpwm2_get_timer_data(lua_State *L) {
lua_pushboolean(L, pwm2_get_module_data()->setupData.isStarted);
lua_pushinteger(L, pwm2_get_module_data()->setupData.interruptTimerCPUTicks);
lua_pushinteger(L, pwm2_get_module_data()->setupData.interruptTimerTicks);
return 3;
}
static int lpwm2_get_pin_data(lua_State *L) {
const uint8 pin = luaL_checkinteger(L, 1);
luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, 1, "invalid pin number");
lua_pushinteger(L, pwm2_is_pin_setup(pin));
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].duty);
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].pulseResolutions);
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].divisableFrequency);
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].frequencyDivisor);
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].resolutionCPUTicks);
lua_pushinteger(L, pwm2_get_module_data()->setupData.pin[pin].resolutionInterruptCounterMultiplier);
return 7;
}
static int lpwm2_setup_pin_common(lua_State *L, const bool isFreqHz) {
if (pwm2_is_started()) {
return luaL_error(L, "pwm2 : already started, stop it before setting up pins.");
}
const int pin = lua_tointeger(L, 1);
const int freq = lua_tointeger(L, 2);
const int resolution = lua_tointeger(L, 3);
const int initDuty = lua_tointeger(L, 4);
const int freqFractions = luaL_optinteger(L, 5, 1);
luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, 1, "invalid pin number");
luaL_argcheck2(L, freq > 0, 2, "invalid frequency");
luaL_argcheck2(L, resolution > 0, 3, "invalid frequency resolution");
luaL_argcheck2(L, initDuty >= 0 && initDuty <= resolution, 4, "invalid duty");
luaL_argcheck2(L, freqFractions > 0, 5, "invalid frequency fractions");
if (isFreqHz) {
pwm2_setup_pin(pin, freqFractions, freq, resolution, initDuty);
} else {
pwm2_setup_pin(pin, freq, freqFractions, resolution, initDuty);
}
return 0;
}
static int lpwm2_setup_pin_hz(lua_State *L) {
return lpwm2_setup_pin_common(L, true);
}
static int lpwm2_setup_pin_sec(lua_State *L) {
return lpwm2_setup_pin_common(L, false);
}
static int lpwm2_set_duty(lua_State *L) {
int pos = 0;
while (true) {
int pin = luaL_optinteger(L, ++pos, -1);
if (pin == -1) {
break;
}
luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, pos, "invalid pin number");
int duty = luaL_optinteger(L, ++pos, -1);
luaL_argcheck2(L, duty >= 0 && duty <= pwm2_get_module_data()->setupData.pin[pin].pulseResolutions, pos, "invalid duty");
if (!pwm2_is_pin_setup(pin)) {
return luaL_error(L, "pwm2 : pin=%d is not setup yet", pin);
}
pwm2_set_duty(pin, duty);
}
return 0;
}
static int lpwm2_release_pin(lua_State *L) {
if (pwm2_is_started()) {
return luaL_error(L, "pwm2 : pwm is started, stop it first.");
}
int pos = 0;
while (true) {
int pin = luaL_optinteger(L, ++pos, -1);
if (pin == -1) {
break;
}
luaL_argcheck2(L, pin > 0 && pin <= GPIO_PIN_NUM, pos, "invalid pin number");
pwm2_release_pin(2);
}
return 0;
}
static int lpwm2_stop(lua_State *L) {
pwm2_stop();
return 0;
}
static int lpwm2_start(lua_State *L) {
if (!pwm2_start()) {
luaL_error(L, "pwm2: currently platform timer1 is being used by another module.\n");
lua_pushboolean(L, false);
} else {
lua_pushboolean(L, true);
}
return 1;
}
// Module function map
LROT_BEGIN(pwm2)
LROT_FUNCENTRY(setup_pin_hz, lpwm2_setup_pin_hz)
LROT_FUNCENTRY(setup_pin_sec, lpwm2_setup_pin_sec)
LROT_FUNCENTRY(release_pin, lpwm2_release_pin)
LROT_FUNCENTRY(start, lpwm2_start)
LROT_FUNCENTRY(stop, lpwm2_stop)
LROT_FUNCENTRY(set_duty, lpwm2_set_duty)
LROT_FUNCENTRY(get_timer_data, lpwm2_get_timer_data)
LROT_FUNCENTRY(get_pin_data, lpwm2_get_pin_data)
// LROT_FUNCENTRY(print_setup, lpwm2_print_setup)
// LROT_FUNCENTRY( time_it, lpwm2_timeit)
// LROT_FUNCENTRY( test_tmr_manual, lpwm2_timing_frc1_manual_load_overhead)
// LROT_FUNCENTRY( test_tmr_auto, lpwm2_timing_frc1_auto_load_overhead)
LROT_END(pwm2, NULL, 0)
NODEMCU_MODULE(PWM2, "pwm2", pwm2, lpwm2_open);
...@@ -81,14 +81,14 @@ static int ICACHE_FLASH_ATTR rc_send(lua_State* L) { ...@@ -81,14 +81,14 @@ static int ICACHE_FLASH_ATTR rc_send(lua_State* L) {
} }
// Module function map // Module function map
static const LUA_REG_TYPE rc_map[] = { LROT_BEGIN(rc)
{ LSTRKEY( "send" ), LFUNCVAL( rc_send )}, LROT_FUNCENTRY( send, rc_send )
{ LNILKEY, LNILVAL} LROT_END( rc, NULL, 0 )
};
int luaopen_rc(lua_State *L) { int luaopen_rc(lua_State *L) {
// TODO: Make sure that the GPIO system is initialized // TODO: Make sure that the GPIO system is initialized
return 0; return 0;
} }
NODEMCU_MODULE(RC, "rc", rc_map, luaopen_rc); NODEMCU_MODULE(RC, "rc", rc, luaopen_rc);
...@@ -102,10 +102,9 @@ static int rfswitch_send( lua_State *L ) ...@@ -102,10 +102,9 @@ static int rfswitch_send( lua_State *L )
} }
// Module function map // Module function map
static const LUA_REG_TYPE rfswitch_map[] = LROT_BEGIN(rfswitch)
{ LROT_FUNCENTRY( send, rfswitch_send )
{ LSTRKEY( "send" ), LFUNCVAL( rfswitch_send ) }, LROT_END( rfswitch, NULL, 0 )
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(RFSWITCH, "rfswitch", rfswitch_map, NULL); NODEMCU_MODULE(RFSWITCH, "rfswitch", rfswitch, NULL);
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
#include "module.h" #include "module.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "platform.h" #include "platform.h"
#include "c_types.h" #include <stdint.h>
#include <stdlib.h>
#include "user_interface.h" #include "user_interface.h"
#include "driver/rotary.h" #include "driver/rotary.h"
#include "../libc/c_stdlib.h"
#define MASK(x) (1 << ROTARY_ ## x ## _INDEX) #define MASK(x) (1 << ROTARY_ ## x ## _INDEX)
...@@ -145,7 +145,7 @@ static int lrotary_setup( lua_State* L ) ...@@ -145,7 +145,7 @@ static int lrotary_setup( lua_State* L )
callback_free(L, id, ROTARY_ALL); callback_free(L, id, ROTARY_ALL);
if (!data[id]) { if (!data[id]) {
data[id] = (DATA *) c_zalloc(sizeof(DATA)); data[id] = (DATA *) calloc(1, sizeof(DATA));
if (!data[id]) { if (!data[id]) {
return -1; return -1;
} }
...@@ -211,7 +211,7 @@ static int lrotary_close( lua_State* L ) ...@@ -211,7 +211,7 @@ static int lrotary_close( lua_State* L )
DATA *d = data[id]; DATA *d = data[id];
if (d) { if (d) {
data[id] = NULL; data[id] = NULL;
c_free(d); free(d);
} }
if (rotary_close( id )) { if (rotary_close( id )) {
...@@ -395,20 +395,20 @@ static int rotary_open(lua_State *L) ...@@ -395,20 +395,20 @@ static int rotary_open(lua_State *L)
} }
// Module function map // Module function map
static const LUA_REG_TYPE rotary_map[] = { LROT_BEGIN(rotary)
{ LSTRKEY( "setup" ), LFUNCVAL( lrotary_setup ) }, LROT_FUNCENTRY( setup, lrotary_setup )
{ LSTRKEY( "close" ), LFUNCVAL( lrotary_close ) }, LROT_FUNCENTRY( close, lrotary_close )
{ LSTRKEY( "on" ), LFUNCVAL( lrotary_on ) }, LROT_FUNCENTRY( on, lrotary_on )
{ LSTRKEY( "getpos" ), LFUNCVAL( lrotary_getpos) }, LROT_FUNCENTRY( getpos, lrotary_getpos )
{ LSTRKEY( "TURN" ), LNUMVAL( MASK(TURN) ) }, LROT_NUMENTRY( TURN, MASK(TURN) )
{ LSTRKEY( "PRESS" ), LNUMVAL( MASK(PRESS) ) }, LROT_NUMENTRY( PRESS, MASK(PRESS) )
{ LSTRKEY( "RELEASE" ), LNUMVAL( MASK(RELEASE) ) }, LROT_NUMENTRY( RELEASE, MASK(RELEASE) )
{ LSTRKEY( "LONGPRESS" ),LNUMVAL( MASK(LONGPRESS) ) }, LROT_NUMENTRY( LONGPRESS, MASK(LONGPRESS) )
{ LSTRKEY( "CLICK" ), LNUMVAL( MASK(CLICK) ) }, LROT_NUMENTRY( CLICK, MASK(CLICK) )
{ LSTRKEY( "DBLCLICK" ), LNUMVAL( MASK(DBLCLICK)) }, LROT_NUMENTRY( DBLCLICK, MASK(DBLCLICK) )
{ LSTRKEY( "ALL" ), LNUMVAL( ROTARY_ALL ) }, LROT_NUMENTRY( ALL, ROTARY_ALL )
{ LNILKEY, LNILVAL } LROT_END( rotary, NULL, 0 )
};
NODEMCU_MODULE(ROTARY, "rotary", rotary_map, rotary_open); NODEMCU_MODULE(ROTARY, "rotary", rotary, rotary_open);
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "rtc/rtctime.h" #include "rtc/rtctime.h"
#define RTCTIME_SLEEP_ALIGNED rtctime_deep_sleep_until_aligned_us #define RTCTIME_SLEEP_ALIGNED rtctime_deep_sleep_until_aligned_us
#include "rtc/rtcfifo.h" #include "rtc/rtcfifo.h"
#include <string.h>
// rtcfifo.prepare ([{sensor_count=n, interval_us=m, storage_begin=x, storage_end=y}]) // rtcfifo.prepare ([{sensor_count=n, interval_us=m, storage_begin=x, storage_end=y}])
static int rtcfifo_prepare (lua_State *L) static int rtcfifo_prepare (lua_State *L)
...@@ -165,18 +166,18 @@ static int rtcfifo_dsleep_until_sample (lua_State *L) ...@@ -165,18 +166,18 @@ static int rtcfifo_dsleep_until_sample (lua_State *L)
#endif #endif
// Module function map // Module function map
static const LUA_REG_TYPE rtcfifo_map[] = { LROT_BEGIN(rtcfifo)
{ LSTRKEY("prepare"), LFUNCVAL(rtcfifo_prepare) }, LROT_FUNCENTRY( prepare, rtcfifo_prepare )
{ LSTRKEY("ready"), LFUNCVAL(rtcfifo_ready) }, LROT_FUNCENTRY( ready, rtcfifo_ready )
{ LSTRKEY("put"), LFUNCVAL(rtcfifo_put) }, LROT_FUNCENTRY( put, rtcfifo_put )
{ LSTRKEY("pop"), LFUNCVAL(rtcfifo_pop) }, LROT_FUNCENTRY( pop, rtcfifo_pop )
{ LSTRKEY("peek"), LFUNCVAL(rtcfifo_peek) }, LROT_FUNCENTRY( peek, rtcfifo_peek )
{ LSTRKEY("drop"), LFUNCVAL(rtcfifo_drop) }, LROT_FUNCENTRY( drop, rtcfifo_drop )
{ LSTRKEY("count"), LFUNCVAL(rtcfifo_count) }, LROT_FUNCENTRY( count, rtcfifo_count )
#ifdef LUA_USE_MODULES_RTCTIME #ifdef LUA_USE_MODULES_RTCTIME
{ LSTRKEY("dsleep_until_sample"), LFUNCVAL(rtcfifo_dsleep_until_sample) }, LROT_FUNCENTRY( dsleep_until_sample, rtcfifo_dsleep_until_sample )
#endif #endif
{ LNILKEY, LNILVAL } LROT_END( rtcfifo, NULL, 0 )
};
NODEMCU_MODULE(RTCFIFO, "rtcfifo", rtcfifo_map, NULL);
NODEMCU_MODULE(RTCFIFO, "rtcfifo", rtcfifo, NULL);
...@@ -41,10 +41,10 @@ static int rtcmem_write32 (lua_State *L) ...@@ -41,10 +41,10 @@ static int rtcmem_write32 (lua_State *L)
// Module function map // Module function map
static const LUA_REG_TYPE rtcmem_map[] = { LROT_BEGIN(rtcmem)
{ LSTRKEY("read32"), LFUNCVAL(rtcmem_read32) }, LROT_FUNCENTRY( read32, rtcmem_read32 )
{ LSTRKEY("write32"), LFUNCVAL(rtcmem_write32) }, LROT_FUNCENTRY( write32, rtcmem_write32 )
{ LNILKEY, LNILVAL } LROT_END( rtcmem, NULL, 0 )
};
NODEMCU_MODULE(RTCMEM, "rtcmem", rtcmem_map, NULL);
NODEMCU_MODULE(RTCMEM, "rtcmem", rtcmem, NULL);
...@@ -46,10 +46,10 @@ void __attribute__((noreturn)) TEXT_SECTION_ATTR rtc_time_enter_deep_sleep_final ...@@ -46,10 +46,10 @@ void __attribute__((noreturn)) TEXT_SECTION_ATTR rtc_time_enter_deep_sleep_final
void rtctime_early_startup (void) void rtctime_early_startup (void)
{ {
Cache_Read_Enable (0, 0, 1); // Cache_Read_Enable (0, 0, 1);
rtc_time_register_bootup (); rtc_time_register_bootup ();
rtc_time_switch_clocks (); rtc_time_switch_clocks ();
Cache_Read_Disable (); // Cache_Read_Disable ();
} }
void rtctime_late_startup (void) void rtctime_late_startup (void)
...@@ -228,14 +228,14 @@ static int rtctime_epoch2cal (lua_State *L) ...@@ -228,14 +228,14 @@ static int rtctime_epoch2cal (lua_State *L)
} }
// Module function map // Module function map
static const LUA_REG_TYPE rtctime_map[] = { LROT_BEGIN(rtctime)
{ LSTRKEY("set"), LFUNCVAL(rtctime_set) }, LROT_FUNCENTRY( set, rtctime_set )
{ LSTRKEY("get"), LFUNCVAL(rtctime_get) }, LROT_FUNCENTRY( get, rtctime_get )
{ LSTRKEY("adjust_delta"), LFUNCVAL(rtctime_adjust_delta) }, LROT_FUNCENTRY( adjust_delta, rtctime_adjust_delta )
{ LSTRKEY("dsleep"), LFUNCVAL(rtctime_dsleep) }, LROT_FUNCENTRY( dsleep, rtctime_dsleep )
{ LSTRKEY("dsleep_aligned"), LFUNCVAL(rtctime_dsleep_aligned) }, LROT_FUNCENTRY( dsleep_aligned, rtctime_dsleep_aligned )
{ LSTRKEY("epoch2cal"), LFUNCVAL(rtctime_epoch2cal) }, LROT_FUNCENTRY( epoch2cal, rtctime_epoch2cal )
{ LNILKEY, LNILVAL } LROT_END( rtctime, NULL, 0 )
};
NODEMCU_MODULE(RTCTIME, "rtctime", rtctime_map, NULL); NODEMCU_MODULE(RTCTIME, "rtctime", rtctime, NULL);
...@@ -247,19 +247,19 @@ static int si7021_lua_firmware(lua_State* L) { ...@@ -247,19 +247,19 @@ static int si7021_lua_firmware(lua_State* L) {
return 1; return 1;
} }
static const LUA_REG_TYPE si7021_map[] = { LROT_BEGIN(si7021)
{ LSTRKEY( "setup" ), LFUNCVAL(si7021_lua_setup) }, LROT_FUNCENTRY( setup, si7021_lua_setup )
{ LSTRKEY( "setting" ), LFUNCVAL(si7021_lua_setting) }, LROT_FUNCENTRY( setting, si7021_lua_setting )
{ LSTRKEY( "read" ), LFUNCVAL(si7021_lua_read) }, LROT_FUNCENTRY( read, si7021_lua_read )
{ LSTRKEY( "serial" ), LFUNCVAL(si7021_lua_serial) }, LROT_FUNCENTRY( serial, si7021_lua_serial )
{ LSTRKEY( "firmware" ), LFUNCVAL(si7021_lua_firmware) }, LROT_FUNCENTRY( firmware, si7021_lua_firmware )
{ LSTRKEY( "RH12_TEMP14" ), LNUMVAL(SI7021_RH12_TEMP14) }, LROT_NUMENTRY( RH12_TEMP14, SI7021_RH12_TEMP14 )
{ LSTRKEY( "RH08_TEMP12" ), LNUMVAL(SI7021_RH08_TEMP12) }, LROT_NUMENTRY( RH08_TEMP12, SI7021_RH08_TEMP12 )
{ LSTRKEY( "RH10_TEMP13" ), LNUMVAL(SI7021_RH10_TEMP13) }, LROT_NUMENTRY( RH10_TEMP13, SI7021_RH10_TEMP13 )
{ LSTRKEY( "RH11_TEMP11" ), LNUMVAL(SI7021_RH11_TEMP11) }, LROT_NUMENTRY( RH11_TEMP11, SI7021_RH11_TEMP11 )
{ LSTRKEY( "HEATER_ENABLE" ), LNUMVAL(SI7021_HEATER_ENABLE) }, LROT_NUMENTRY( HEATER_ENABLE, SI7021_HEATER_ENABLE )
{ LSTRKEY( "HEATER_DISABLE" ), LNUMVAL(SI7021_HEATER_DISABLE) }, LROT_NUMENTRY( HEATER_DISABLE, SI7021_HEATER_DISABLE )
{ LNILKEY, LNILVAL } LROT_END( si7021, NULL, 0 )
};
NODEMCU_MODULE(SI7021, "si7021", si7021_map, NULL); NODEMCU_MODULE(SI7021, "si7021", si7021, NULL);
...@@ -74,14 +74,13 @@ static int sigma_delta_settarget( lua_State *L ) ...@@ -74,14 +74,13 @@ static int sigma_delta_settarget( lua_State *L )
// Module function map // Module function map
static const LUA_REG_TYPE sigma_delta_map[] = LROT_BEGIN(sigma_delta)
{ LROT_FUNCENTRY( setup, sigma_delta_setup )
{ LSTRKEY( "setup" ), LFUNCVAL( sigma_delta_setup ) }, LROT_FUNCENTRY( close, sigma_delta_close )
{ LSTRKEY( "close" ), LFUNCVAL( sigma_delta_close ) }, LROT_FUNCENTRY( setpwmduty, sigma_delta_setpwmduty )
{ LSTRKEY( "setpwmduty" ), LFUNCVAL( sigma_delta_setpwmduty ) }, LROT_FUNCENTRY( setprescale, sigma_delta_setprescale )
{ LSTRKEY( "setprescale" ), LFUNCVAL( sigma_delta_setprescale ) }, LROT_FUNCENTRY( settarget, sigma_delta_settarget )
{ LSTRKEY( "settarget" ), LFUNCVAL( sigma_delta_settarget ) }, LROT_END( sigma_delta, NULL, 0 )
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta, NULL);
NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta_map, NULL);
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
#ifndef LOCAL_LUA #ifndef LOCAL_LUA
#include "module.h" #include "module.h"
#include "c_string.h" #include <string.h>
#include "c_math.h" #include <math.h>
#include "c_limits.h" #include <limits.h>
#endif #endif
#include "json_config.h" #include "sjson/json_config.h"
#include "jsonsl.h" #include "sjson/jsonsl.h"
#define LUA_SJSONLIBNAME "sjson" #define LUA_SJSONLIBNAME "sjson"
...@@ -992,74 +992,33 @@ static int sjson_encoder_destructor(lua_State *L) { ...@@ -992,74 +992,33 @@ static int sjson_encoder_destructor(lua_State *L) {
return 0; return 0;
} }
#ifdef LOCAL_LUA LROT_BEGIN(sjson_encoder)
static const luaL_Reg sjson_encoder_map[] = { LROT_FUNCENTRY( read, sjson_encoder_read )
{ "read", sjson_encoder_read }, LROT_FUNCENTRY( __gc, sjson_encoder_destructor )
{ "__gc", sjson_encoder_destructor }, LROT_TABENTRY( __index, sjson_encoder )
{ NULL, NULL } LROT_END( sjson_encoder, sjson_encoder, LROT_MASK_GC_INDEX )
};
static const luaL_Reg sjson_decoder_map[] = { LROT_BEGIN(sjson_decoder)
{ "write", sjson_decoder_write }, LROT_FUNCENTRY( write, sjson_decoder_write )
{ "result", sjson_decoder_result }, LROT_FUNCENTRY( result, sjson_decoder_result )
{ "__gc", sjson_decoder_destructor }, LROT_FUNCENTRY( __gc, sjson_decoder_destructor )
{ NULL, NULL } LROT_TABENTRY( __index, sjson_decoder )
}; LROT_END( sjson_decoder, sjson_decoder, LROT_MASK_GC_INDEX )
static const luaL_Reg sjsonlib[] = {
{ "decode", sjson_decode }, LROT_BEGIN(sjson)
{ "decoder", sjson_decoder }, LROT_FUNCENTRY( encode, sjson_encode )
{ "encode", sjson_encode }, LROT_FUNCENTRY( decode, sjson_decode )
{ "encoder", sjson_encoder }, LROT_FUNCENTRY( encoder, sjson_encoder )
{NULL, NULL} LROT_FUNCENTRY( decoder, sjson_decoder )
}; LROT_LUDENTRY( NULL, 0 )
#else LROT_END( sjson, NULL, 0 )
static const LUA_REG_TYPE sjson_encoder_map[] = {
{ LSTRKEY( "read" ), LFUNCVAL( sjson_encoder_read ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( sjson_encoder_destructor ) },
{ LSTRKEY( "__index" ), LROVAL( sjson_encoder_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE sjson_decoder_map[] = {
{ LSTRKEY( "write" ), LFUNCVAL( sjson_decoder_write ) },
{ LSTRKEY( "result" ), LFUNCVAL( sjson_decoder_result ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( sjson_decoder_destructor ) },
{ LSTRKEY( "__index" ), LROVAL( sjson_decoder_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE sjson_map[] = {
{ LSTRKEY( "encode" ), LFUNCVAL( sjson_encode ) },
{ LSTRKEY( "decode" ), LFUNCVAL( sjson_decode ) },
{ LSTRKEY( "encoder" ), LFUNCVAL( sjson_encoder ) },
{ LSTRKEY( "decoder" ), LFUNCVAL( sjson_decoder ) },
{ LSTRKEY( "NULL" ), LUDATA( 0 ) },
{ LNILKEY, LNILVAL }
};
#endif
LUALIB_API int luaopen_sjson (lua_State *L) { LUALIB_API int luaopen_sjson (lua_State *L) {
#ifdef LOCAL_LUA luaL_rometatable(L, "sjson.decoder", LROT_TABLEREF(sjson_decoder));
luaL_register(L, LUA_SJSONLIBNAME, sjsonlib); luaL_rometatable(L, "sjson.encoder", LROT_TABLEREF(sjson_encoder));
lua_getglobal(L, LUA_SJSONLIBNAME);
lua_pushstring(L, "NULL");
lua_pushlightuserdata(L, 0);
lua_settable(L, -3);
lua_pop(L, 1);
luaL_newmetatable(L, "sjson.encoder");
luaL_register(L, NULL, sjson_encoder_map);
lua_setfield(L, -1, "__index");
luaL_newmetatable(L, "sjson.decoder");
luaL_register(L, NULL, sjson_decoder_map);
lua_setfield(L, -1, "__index");
#else
luaL_rometatable(L, "sjson.decoder", (void *)sjson_decoder_map);
luaL_rometatable(L, "sjson.encoder", (void *)sjson_encoder_map);
#endif
return 1; return 1;
} }
#ifndef LOCAL_LUA NODEMCU_MODULE(SJSON, "sjson", sjson, luaopen_sjson);
NODEMCU_MODULE(SJSON, "sjson", sjson_map, luaopen_sjson);
#endif
...@@ -38,7 +38,9 @@ ...@@ -38,7 +38,9 @@
#include "os_type.h" #include "os_type.h"
#include "osapi.h" #include "osapi.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "c_stdlib.h" #include <stdlib.h>
#include "lwip/inet.h"
#include "lwip/dhcp.h"
#include "user_modules.h" #include "user_modules.h"
#include "lwip/dns.h" #include "lwip/dns.h"
#include "task/task.h" #include "task/task.h"
...@@ -48,6 +50,8 @@ ...@@ -48,6 +50,8 @@
#include "rtc/rtctime.h" #include "rtc/rtctime.h"
#endif #endif
struct netif * eagle_lwip_getif(uint8 index);
#define max(a,b) ((a < b) ? b : a) #define max(a,b) ((a < b) ? b : a)
#define NTP_PORT 123 #define NTP_PORT 123
...@@ -180,18 +184,18 @@ static void cleanup (lua_State *L) ...@@ -180,18 +184,18 @@ static void cleanup (lua_State *L)
luaL_unref (L, LUA_REGISTRYINDEX, state->sync_cb_ref); luaL_unref (L, LUA_REGISTRYINDEX, state->sync_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, state->err_cb_ref); luaL_unref (L, LUA_REGISTRYINDEX, state->err_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref); luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
os_free (state); free (state);
state = 0; state = 0;
} }
static ip_addr_t* get_free_server() { static ip_addr_t* get_free_server() {
ip_addr_t* temp = (ip_addr_t *) c_malloc((server_count + 1) * sizeof(ip_addr_t)); ip_addr_t* temp = (ip_addr_t *) malloc((server_count + 1) * sizeof(ip_addr_t));
if (server_count > 0) { if (server_count > 0) {
memcpy(temp, serverp, server_count * sizeof(ip_addr_t)); memcpy(temp, serverp, server_count * sizeof(ip_addr_t));
} }
if (serverp) { if (serverp) {
c_free(serverp); free(serverp);
} }
serverp = temp; serverp = temp;
...@@ -623,7 +627,7 @@ static void sntp_dolookups (lua_State *L) { ...@@ -623,7 +627,7 @@ static void sntp_dolookups (lua_State *L) {
// Step through each element of the table, converting it to an address // Step through each element of the table, converting it to an address
// at the end, start the lookups. If we have already looked everything up, // at the end, start the lookups. If we have already looked everything up,
// then move straight to sending the packets. // then move straight to sending the packets.
if (state->list_ref == LUA_NOREF) { if ((state->list_ref == LUA_NOREF) || (state->list_ref == LUA_REFNIL)) {
sntp_dosend(); sntp_dosend();
return; return;
} }
...@@ -671,7 +675,7 @@ static void sntp_dolookups (lua_State *L) { ...@@ -671,7 +675,7 @@ static void sntp_dolookups (lua_State *L) {
} }
static char *state_init(lua_State *L) { static char *state_init(lua_State *L) {
state = (sntp_state_t *)c_malloc (sizeof (sntp_state_t)); state = (sntp_state_t *)malloc (sizeof (sntp_state_t));
if (!state) if (!state)
return ("out of memory"); return ("out of memory");
...@@ -698,9 +702,17 @@ static char *state_init(lua_State *L) { ...@@ -698,9 +702,17 @@ static char *state_init(lua_State *L) {
static char *set_repeat_mode(lua_State *L, bool enable) static char *set_repeat_mode(lua_State *L, bool enable)
{ {
if (repeat) {
os_timer_disarm (&repeat->timer);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->sync_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->err_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->list_ref);
free(repeat);
repeat = NULL;
}
if (enable) { if (enable) {
set_repeat_mode(L, FALSE); repeat = (sntp_repeat_t *) malloc(sizeof(sntp_repeat_t));
repeat = (sntp_repeat_t *) c_malloc(sizeof(sntp_repeat_t));
if (!repeat) { if (!repeat) {
return "no memory"; return "no memory";
} }
...@@ -716,16 +728,8 @@ static char *set_repeat_mode(lua_State *L, bool enable) ...@@ -716,16 +728,8 @@ static char *set_repeat_mode(lua_State *L, bool enable)
//The function on_long_timeout returns errors to the developer //The function on_long_timeout returns errors to the developer
//My guess: Error reporting is a good thing, resume the timer. //My guess: Error reporting is a good thing, resume the timer.
os_timer_arm(&repeat->timer, 1000 * 1000, 1); os_timer_arm(&repeat->timer, 1000 * 1000, 1);
} else {
if (repeat) {
os_timer_disarm (&repeat->timer);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->sync_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->err_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, repeat->list_ref);
c_free(repeat);
repeat = NULL;
}
} }
return NULL; return NULL;
} }
...@@ -787,43 +791,43 @@ static int sntp_sync (lua_State *L) ...@@ -787,43 +791,43 @@ static int sntp_sync (lua_State *L)
if (lua_istable(L, 1)) { if (lua_istable(L, 1)) {
// Save a reference to the table // Save a reference to the table
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
state->list_ref = luaL_ref(L, LUA_REGISTRYINDEX);
sntp_dolookups(L);
goto good_ret;
} else { } else {
size_t l; size_t l;
const char *hostname = luaL_checklstring(L, 1, &l); const char *hostname = luaL_checklstring(L, 1, &l);
if (l>128 || hostname == NULL) if (l>128 || hostname == NULL)
sync_err("need <128 hostname"); sync_err("need <128 hostname");
err_t err = dns_gethostbyname(hostname, get_free_server(), sntp_dns_found, state);
if (err == ERR_INPROGRESS) {
goto good_ret;
} else if (err == ERR_ARG)
sync_err("bad hostname");
server_count++; /* Construct a singleton table containing the one server */
lua_newtable(L);
lua_pushnumber(L, 1);
lua_pushstring(L, hostname);
lua_settable(L, -3);
} }
} else if (server_count == 0) { } else if (server_count == 0) {
// default to ntp pool
lua_newtable(L); lua_newtable(L);
struct netif *iface = (struct netif *)eagle_lwip_getif(0x00);
if (iface->dhcp && iface->dhcp->offered_ntp_addr.addr) {
ip_addr_t ntp_addr = iface->dhcp->offered_ntp_addr;
lua_pushnumber(L, 1);
lua_pushstring(L, inet_ntoa(ntp_addr));
lua_settable(L, -3);
} else {
// default to ntp pool
int i; int i;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
lua_pushnumber(L, i + 1); lua_pushnumber(L, i + 1);
char buf[64]; char buf[64];
c_sprintf(buf, "%d.nodemcu.pool.ntp.org", i); sprintf(buf, "%d.nodemcu.pool.ntp.org", i);
lua_pushstring(L, buf); lua_pushstring(L, buf);
lua_settable(L, -3); lua_settable(L, -3);
} }
}
}
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref); luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
state->list_ref = luaL_ref(L, LUA_REGISTRYINDEX); state->list_ref = luaL_ref(L, LUA_REGISTRYINDEX);
sntp_dolookups(L); sntp_dolookups(L);
goto good_ret;
}
sntp_dosend ();
good_ret:
if (!lua_isnoneornil(L, 4)) { if (!lua_isnoneornil(L, 4)) {
set_repeat_mode(L, 1); set_repeat_mode(L, 1);
} }
...@@ -835,7 +839,7 @@ error: ...@@ -835,7 +839,7 @@ error:
{ {
if (state->pcb) if (state->pcb)
udp_remove (state->pcb); udp_remove (state->pcb);
c_free (state); free (state);
state = 0; state = 0;
} }
return luaL_error (L, errmsg); return luaL_error (L, errmsg);
...@@ -869,13 +873,13 @@ static int sntp_open(lua_State *L) ...@@ -869,13 +873,13 @@ static int sntp_open(lua_State *L)
// Module function map // Module function map
static const LUA_REG_TYPE sntp_map[] = { LROT_BEGIN(sntp)
{ LSTRKEY("sync"), LFUNCVAL(sntp_sync) }, LROT_FUNCENTRY( sync, sntp_sync )
#ifdef LUA_USE_MODULES_RTCTIME #ifdef LUA_USE_MODULES_RTCTIME
{ LSTRKEY("setoffset"), LFUNCVAL(sntp_setoffset) }, LROT_FUNCENTRY( setoffset, sntp_setoffset )
{ LSTRKEY("getoffset"), LFUNCVAL(sntp_getoffset) }, LROT_FUNCENTRY( getoffset, sntp_getoffset )
#endif #endif
{ LNILKEY, LNILVAL } LROT_END( sntp, NULL, 0 )
};
NODEMCU_MODULE(SNTP, "sntp", sntp_map, sntp_open); NODEMCU_MODULE(SNTP, "sntp", sntp, sntp_open);
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