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 @@
#include "module.h"
#include "lauxlib.h"
#include "c_string.h"
#include "c_stdlib.h"
#include <string.h>
#include <stdlib.h>
#include <alloca.h>
#include "c_types.h"
#include "mem.h"
#include <stdint.h>
#include "lwip/ip_addr.h"
#include "nodemcu_mdns.h"
#include "user_interface.h"
......@@ -43,16 +43,16 @@ static int mdns_register(lua_State *L)
luaL_checktype(L, -2, LUA_TSTRING);
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);
} else if (c_strcmp(key, "service") == 0) {
} else if (strcmp(key, "service") == 0) {
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);
} else {
int len = c_strlen(key) + 1;
int len = strlen(key) + 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);
strcat(p, "=");
strcat(p, value);
......@@ -88,10 +88,10 @@ static int mdns_register(lua_State *L)
}
// Module function map
static const LUA_REG_TYPE mdns_map[] = {
{ LSTRKEY("register"), LFUNCVAL(mdns_register) },
{ LSTRKEY("close"), LFUNCVAL(mdns_close) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(mdns)
LROT_FUNCENTRY( register, mdns_register )
LROT_FUNCENTRY( close, mdns_close )
LROT_END( mdns, NULL, 0 )
NODEMCU_MODULE(MDNS, "mdns", mdns_map, NULL);
NODEMCU_MODULE(MDNS, "mdns", mdns, NULL);
......@@ -4,16 +4,16 @@
#include "lauxlib.h"
#include "platform.h"
#include "c_string.h"
#include "c_stdlib.h"
#include <string.h>
#include <stddef.h>
#include "c_types.h"
#include <stdint.h>
#include "mem.h"
#include "lwip/ip_addr.h"
#include "espconn.h"
#include "mqtt_msg.h"
#include "msg_queue.h"
#include "mqtt/mqtt_msg.h"
#include "mqtt/msg_queue.h"
#include "user_interface.h"
......@@ -50,10 +50,6 @@ typedef struct mqtt_event_data_t
uint16_t data_offset;
} mqtt_event_data_t;
#define RECONNECT_OFF 0
#define RECONNECT_POSSIBLE 1
#define RECONNECT_ON 2
typedef enum {
MQTT_RECV_NORMAL,
MQTT_RECV_BUFFERING_SHORT,
......@@ -64,7 +60,6 @@ typedef enum {
typedef struct mqtt_state_t
{
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_connection_t mqtt_connection;
msg_queue_t* pending_msg_q;
......@@ -138,37 +133,25 @@ static void mqtt_socket_disconnected(void *arg) // tcp only
}
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_size = 0;
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){
mud->pesp_conn->reverse = NULL;
if(mud->pesp_conn->proto.tcp)
c_free(mud->pesp_conn->proto.tcp);
mud->pesp_conn->proto.tcp = NULL;
c_free(mud->pesp_conn);
mud->pesp_conn = NULL;
}
mud->connected = false;
luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref);
mud->self_ref = LUA_NOREF; // unref this, and the mqtt.socket userdata will delete it self
if(mud->pesp_conn){
mud->pesp_conn->reverse = NULL;
if(mud->pesp_conn->proto.tcp)
free(mud->pesp_conn->proto.tcp);
mud->pesp_conn->proto.tcp = NULL;
free(mud->pesp_conn);
mud->pesp_conn = NULL;
}
mud->connected = false;
luaL_unref(L, LUA_REGISTRYINDEX, mud->self_ref);
mud->self_ref = LUA_NOREF; // unref this, and the mqtt.socket userdata will delete it self
if(call_back){
lua_call(L, 1, 0);
}
......@@ -191,24 +174,18 @@ static void mqtt_socket_reconnected(void *arg, sint8_t err)
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
if (mud->secure) {
espconn_secure_disconnect(pesp_conn);
} else
if (mud->secure) {
espconn_secure_disconnect(pesp_conn);
} else
#endif
{
espconn_disconnect(pesp_conn);
}
{
espconn_disconnect(pesp_conn);
}
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");
}
......@@ -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.
// 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.
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) {
NODE_DBG("MQTT[buffering-short]: Failed to allocate %u bytes, disconnecting...\n", mud->mqtt_state.recv_buffer_size + len);
#ifdef CLIENT_SSL_ENABLE
......@@ -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);
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);
c_free(mud->mqtt_state.recv_buffer);
free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL;
mud->mqtt_state.recv_buffer_state = MQTT_RECV_NORMAL;
......@@ -475,9 +452,6 @@ READPACKET:
mud->keepalive_sent = 0;
luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_connect_fail_ref);
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)
break;
if(mud->self_ref == LUA_NOREF)
......@@ -559,7 +533,7 @@ READPACKET:
// max_message_length is 16bit.
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) {
NODE_DBG("MQTT: Failed to allocate %u bytes, disconnecting...\n", alloc_size);
#ifdef CLIENT_SSL_ENABLE
......@@ -700,7 +674,7 @@ RX_MESSAGE_PROCESSED:
if(continuation_buffer != NULL) {
NODE_DBG("MQTT[buffering]: buffered message finished. Continuing with rest of rx buffer (%u)\n",
len);
c_free(mud->mqtt_state.recv_buffer);
free(mud->mqtt_state.recv_buffer);
mud->mqtt_state.recv_buffer = NULL;
in_buffer = continuation_buffer;
......@@ -724,7 +698,7 @@ RX_MESSAGE_PROCESSED:
RX_PACKET_FINISHED:
if(temp_pdata != NULL) {
c_free(temp_pdata);
free(temp_pdata);
}
mqtt_send_if_possible(pesp_conn);
......@@ -928,12 +902,12 @@ static int mqtt_socket_client( lua_State* L )
lmqtt_userdata *mud;
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("\n");
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;
int keepalive = 0;
int stack = 1;
......@@ -943,7 +917,7 @@ static int mqtt_socket_client( lua_State* L )
// create a object
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
mud->self_ref = LUA_NOREF;
mud->cb_connect_ref = LUA_NOREF;
......@@ -1015,30 +989,30 @@ static int mqtt_socket_client( lua_State* L )
}
// TODO: check the zalloc result.
mud->connect_info.client_id = (uint8_t *)c_zalloc(idl+1);
mud->connect_info.username = (uint8_t *)c_zalloc(unl + 1);
mud->connect_info.password = (uint8_t *)c_zalloc(pwl + 1);
mud->connect_info.client_id = (uint8_t *)calloc(1,idl+1);
mud->connect_info.username = (uint8_t *)calloc(1,unl + 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) {
c_free(mud->connect_info.client_id);
free(mud->connect_info.client_id);
mud->connect_info.client_id = NULL;
}
if(mud->connect_info.username) {
c_free(mud->connect_info.username);
free(mud->connect_info.username);
mud->connect_info.username = NULL;
}
if(mud->connect_info.password) {
c_free(mud->connect_info.password);
free(mud->connect_info.password);
mud->connect_info.password = NULL;
}
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;
c_memcpy(mud->connect_info.username, username, unl);
memcpy(mud->connect_info.username, username, unl);
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;
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 )
mud->connect_info.max_message_length = max_message_length;
mud->mqtt_state.pending_msg_q = NULL;
mud->mqtt_state.auto_reconnect = RECONNECT_OFF;
mud->mqtt_state.port = 1883;
mud->mqtt_state.connect_info = &mud->connect_info;
mud->mqtt_state.recv_buffer = NULL;
......@@ -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
mud->pesp_conn->reverse = NULL;
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;
c_free(mud->pesp_conn);
free(mud->pesp_conn);
mud->pesp_conn = NULL; // for socket, it will free this when disconnected
}
while(mud->mqtt_state.pending_msg_q) {
......@@ -1093,34 +1066,34 @@ static int mqtt_delete( lua_State* L )
// ---- alloc-ed in mqtt_socket_lwt()
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;
}
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;
}
// ----
//--------- alloc-ed in mqtt_socket_received()
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;
}
// ----
//--------- alloc-ed in mqtt_socket_client()
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;
}
if(mud->connect_info.username){
c_free(mud->connect_info.username);
free(mud->connect_info.username);
mud->connect_info.username = NULL;
}
if(mud->connect_info.password){
c_free(mud->connect_info.password);
free(mud->connect_info.password);
mud->connect_info.password = NULL;
}
// -------
......@@ -1230,7 +1203,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
if(ipaddr->addr != 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(IPSTR, IP2STR(&(ipaddr->addr)));
NODE_DBG("\n");
......@@ -1242,7 +1215,7 @@ static sint8 socket_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
}
#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 )
{
NODE_DBG("enter mqtt_socket_connect.\n");
......@@ -1252,7 +1225,7 @@ static int mqtt_socket_connect( lua_State* L )
ip_addr_t ipaddr;
const char *domain;
int stack = 1;
unsigned secure = 0, auto_reconnect = RECONNECT_OFF;
unsigned secure = 0;
int top = lua_gettop(L);
sint8 espconn_status;
......@@ -1268,7 +1241,7 @@ static int mqtt_socket_connect( lua_State* L )
struct espconn *pesp_conn = mud->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 {
espconn_delete(pesp_conn);
}
......@@ -1276,9 +1249,9 @@ static int mqtt_socket_connect( lua_State* L )
if(!pesp_conn)
return luaL_error(L, "not enough memory");
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){
c_free(pesp_conn);
free(pesp_conn);
pesp_conn = mud->pesp_conn = NULL;
return luaL_error(L, "not enough memory");
}
......@@ -1298,7 +1271,7 @@ static int mqtt_socket_connect( lua_State* L )
domain = "127.0.0.1";
}
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(IPSTR, IP2STR(&ipaddr.addr));
NODE_DBG("\n");
......@@ -1315,13 +1288,15 @@ static int mqtt_socket_connect( lua_State* L )
pesp_conn->proto.tcp->local_port = espconn_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);
stack++;
if ( secure != 0 && secure != 1 ){
secure = 0; // default to 0
if (lua_isnumber(L, stack)) {
platform_print_deprecation_note("mqtt.connect secure parameter as integer","in the future");
secure = !!lua_tointeger(L, stack);
} else {
secure = lua_toboolean(L, stack);
}
stack++;
} else {
secure = 0; // default to 0
}
......@@ -1334,19 +1309,6 @@ static int mqtt_socket_connect( lua_State* L )
}
#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
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
......@@ -1378,7 +1340,7 @@ static int mqtt_socket_connect( lua_State* L )
//My guess: If in doubt, resume the timer
// 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;
dns_reconn_count = 0;
......@@ -1416,8 +1378,6 @@ static int mqtt_socket_close( lua_State* L )
return 1;
}
mud->mqtt_state.auto_reconnect = RECONNECT_OFF; // stop auto reconnect.
sint8 espconn_status = ESPCONN_CONN;
if (mud->connected) {
// Send disconnect message
......@@ -1474,18 +1434,27 @@ static int mqtt_socket_on( lua_State* L )
luaL_checkanyfunction(L, 3);
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);
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);
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);
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);
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{
lua_pop(L, 1);
return luaL_error( L, "method not supported" );
......@@ -1826,30 +1795,30 @@ static int mqtt_socket_lwt( lua_State* L )
}
stack++;
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;
}
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_topic = (uint8_t*) c_zalloc( topicSize + 1 );
mud->connect_info.will_message = (uint8_t*) c_zalloc( msgSize + 1 );
mud->connect_info.will_topic = (uint8_t*) calloc(1, topicSize + 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){
c_free(mud->connect_info.will_topic);
free(mud->connect_info.will_topic);
mud->connect_info.will_topic = NULL;
}
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;
}
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;
c_memcpy(mud->connect_info.will_message, lwtMsg, msgSize);
memcpy(mud->connect_info.will_message, lwtMsg, msgSize);
mud->connect_info.will_message[msgSize] = 0;
if ( lua_isnumber(L, stack) )
......@@ -1873,43 +1842,43 @@ static int mqtt_socket_lwt( lua_State* L )
}
// Module function map
static const LUA_REG_TYPE mqtt_socket_map[] = {
{ LSTRKEY( "connect" ), LFUNCVAL( mqtt_socket_connect ) },
{ LSTRKEY( "close" ), LFUNCVAL( mqtt_socket_close ) },
{ LSTRKEY( "publish" ), LFUNCVAL( mqtt_socket_publish ) },
{ LSTRKEY( "subscribe" ), LFUNCVAL( mqtt_socket_subscribe ) },
{ LSTRKEY( "unsubscribe" ), LFUNCVAL( mqtt_socket_unsubscribe ) },
{ LSTRKEY( "lwt" ), LFUNCVAL( mqtt_socket_lwt ) },
{ LSTRKEY( "on" ), LFUNCVAL( mqtt_socket_on ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( mqtt_delete ) },
{ LSTRKEY( "__index" ), LROVAL( mqtt_socket_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE mqtt_map[] = {
{ LSTRKEY( "Client" ), LFUNCVAL( mqtt_socket_client ) },
{ LSTRKEY( "CONN_FAIL_SERVER_NOT_FOUND" ), LNUMVAL( MQTT_CONN_FAIL_SERVER_NOT_FOUND ) },
{ LSTRKEY( "CONN_FAIL_NOT_A_CONNACK_MSG" ), LNUMVAL( MQTT_CONN_FAIL_NOT_A_CONNACK_MSG ) },
{ LSTRKEY( "CONN_FAIL_DNS" ), LNUMVAL( MQTT_CONN_FAIL_DNS ) },
{ LSTRKEY( "CONN_FAIL_TIMEOUT_RECEIVING" ), LNUMVAL( MQTT_CONN_FAIL_TIMEOUT_RECEIVING ) },
{ LSTRKEY( "CONN_FAIL_TIMEOUT_SENDING" ), LNUMVAL( MQTT_CONN_FAIL_TIMEOUT_SENDING ) },
{ LSTRKEY( "CONNACK_ACCEPTED" ), LNUMVAL( MQTT_CONNACK_ACCEPTED ) },
{ LSTRKEY( "CONNACK_REFUSED_PROTOCOL_VER" ), LNUMVAL( MQTT_CONNACK_REFUSED_PROTOCOL_VER ) },
{ LSTRKEY( "CONNACK_REFUSED_ID_REJECTED" ), LNUMVAL( MQTT_CONNACK_REFUSED_ID_REJECTED ) },
{ LSTRKEY( "CONNACK_REFUSED_SERVER_UNAVAILABLE" ), LNUMVAL( MQTT_CONNACK_REFUSED_SERVER_UNAVAILABLE ) },
{ LSTRKEY( "CONNACK_REFUSED_BAD_USER_OR_PASS" ), LNUMVAL( MQTT_CONNACK_REFUSED_BAD_USER_OR_PASS ) },
{ LSTRKEY( "CONNACK_REFUSED_NOT_AUTHORIZED" ), LNUMVAL( MQTT_CONNACK_REFUSED_NOT_AUTHORIZED ) },
{ LSTRKEY( "__metatable" ), LROVAL( mqtt_map ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(mqtt_socket)
LROT_FUNCENTRY( connect, mqtt_socket_connect )
LROT_FUNCENTRY( close, mqtt_socket_close )
LROT_FUNCENTRY( publish, mqtt_socket_publish )
LROT_FUNCENTRY( subscribe, mqtt_socket_subscribe )
LROT_FUNCENTRY( unsubscribe, mqtt_socket_unsubscribe )
LROT_FUNCENTRY( lwt, mqtt_socket_lwt )
LROT_FUNCENTRY( on, mqtt_socket_on )
LROT_FUNCENTRY( __gc, mqtt_delete )
LROT_TABENTRY( __index, mqtt_socket )
LROT_END( mqtt_socket, mqtt_socket, 0 )
LROT_BEGIN(mqtt)
LROT_FUNCENTRY( Client, mqtt_socket_client )
LROT_NUMENTRY( CONN_FAIL_SERVER_NOT_FOUND, MQTT_CONN_FAIL_SERVER_NOT_FOUND )
LROT_NUMENTRY( CONN_FAIL_NOT_A_CONNACK_MSG, MQTT_CONN_FAIL_NOT_A_CONNACK_MSG )
LROT_NUMENTRY( CONN_FAIL_DNS, MQTT_CONN_FAIL_DNS )
LROT_NUMENTRY( CONN_FAIL_TIMEOUT_RECEIVING, MQTT_CONN_FAIL_TIMEOUT_RECEIVING )
LROT_NUMENTRY( CONN_FAIL_TIMEOUT_SENDING, MQTT_CONN_FAIL_TIMEOUT_SENDING )
LROT_NUMENTRY( CONNACK_ACCEPTED, MQTT_CONNACK_ACCEPTED )
LROT_NUMENTRY( CONNACK_REFUSED_PROTOCOL_VER, MQTT_CONNACK_REFUSED_PROTOCOL_VER )
LROT_NUMENTRY( CONNACK_REFUSED_ID_REJECTED, MQTT_CONNACK_REFUSED_ID_REJECTED )
LROT_NUMENTRY( CONNACK_REFUSED_SERVER_UNAVAILABLE, MQTT_CONNACK_REFUSED_SERVER_UNAVAILABLE )
LROT_NUMENTRY( CONNACK_REFUSED_BAD_USER_OR_PASS, MQTT_CONNACK_REFUSED_BAD_USER_OR_PASS )
LROT_NUMENTRY( CONNACK_REFUSED_NOT_AUTHORIZED, MQTT_CONNACK_REFUSED_NOT_AUTHORIZED )
LROT_TABENTRY( __metatable, mqtt )
LROT_END( mqtt, mqtt, 0 )
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;
}
NODEMCU_MODULE(MQTT, "mqtt", mqtt_map, luaopen_mqtt);
NODEMCU_MODULE(MQTT, "mqtt", mqtt, luaopen_mqtt);
......@@ -5,10 +5,11 @@
#include "platform.h"
#include "lmem.h"
#include "c_string.h"
#include "c_stdlib.h"
#include <string.h>
#include <strings.h>
#include <stddef.h>
#include "c_types.h"
#include <stdint.h>
#include "mem.h"
#include "osapi.h"
#include "lwip/err.h"
......@@ -875,14 +876,14 @@ static void net_dns_static_cb(const char *name, ip_addr_t *ipaddr, void *callbac
addr = *ipaddr;
else addr.addr = 0xFFFFFFFF;
int cb_ref = ((int*)callback_arg)[0];
c_free(callback_arg);
free(callback_arg);
lua_State *L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref);
lua_pushnil(L);
if (addr.addr != 0xFFFFFFFF) {
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);
} else {
lua_pushnil(L);
......@@ -906,7 +907,7 @@ static int net_dns_static( lua_State* L ) {
if (cbref == LUA_NOREF) {
return luaL_error(L, "wrong callback");
}
int *cbref_ptr = c_zalloc(sizeof(int));
int *cbref_ptr = calloc(1, sizeof(int));
cbref_ptr[0] = cbref;
ip_addr_t addr;
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 ) {
return 0;
} else {
int e = lwip_lua_checkerr(L, err);
c_free(cbref_ptr);
free(cbref_ptr);
return e;
}
return 0;
......@@ -958,7 +959,7 @@ static int net_getdnsserver( lua_State* L ) {
lua_pushnil( L );
} else {
char temp[20] = {0};
c_sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) );
sprintf(temp, IPSTR, IP2STR( &ipaddr.addr ) );
lua_pushstring( L, temp );
}
......@@ -968,79 +969,79 @@ static int net_getdnsserver( lua_State* L ) {
#pragma mark - Tables
#ifdef TLS_MODULE_PRESENT
extern const LUA_REG_TYPE tls_cert_map[];
LROT_EXTERN(tls_cert);
#endif
// Module function map
static const LUA_REG_TYPE net_tcpserver_map[] = {
{ LSTRKEY( "listen" ), LFUNCVAL( net_listen ) },
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
{ LSTRKEY( "__index" ), LROVAL( net_tcpserver_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE net_tcpsocket_map[] = {
{ LSTRKEY( "connect" ), LFUNCVAL( net_connect ) },
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) },
{ LSTRKEY( "on" ), LFUNCVAL( net_on ) },
{ LSTRKEY( "send" ), LFUNCVAL( net_send ) },
{ LSTRKEY( "hold" ), LFUNCVAL( net_hold ) },
{ LSTRKEY( "unhold" ), LFUNCVAL( net_unhold ) },
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
{ LSTRKEY( "getpeer" ), LFUNCVAL( net_getpeer ) },
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
{ LSTRKEY( "__index" ), LROVAL( net_tcpsocket_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE net_udpsocket_map[] = {
{ LSTRKEY( "listen" ), LFUNCVAL( net_listen ) },
{ LSTRKEY( "close" ), LFUNCVAL( net_close ) },
{ LSTRKEY( "on" ), LFUNCVAL( net_on ) },
{ LSTRKEY( "send" ), LFUNCVAL( net_send ) },
{ LSTRKEY( "dns" ), LFUNCVAL( net_dns ) },
{ LSTRKEY( "ttl" ), LFUNCVAL( net_ttl ) },
{ LSTRKEY( "getaddr" ), LFUNCVAL( net_getaddr ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( net_delete ) },
{ LSTRKEY( "__index" ), LROVAL( net_udpsocket_map ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE net_dns_map[] = {
{ LSTRKEY( "setdnsserver" ), LFUNCVAL( net_setdnsserver ) },
{ LSTRKEY( "getdnsserver" ), LFUNCVAL( net_getdnsserver ) },
{ LSTRKEY( "resolve" ), LFUNCVAL( net_dns_static ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE net_map[] = {
{ LSTRKEY( "createServer" ), LFUNCVAL( net_createServer ) },
{ LSTRKEY( "createConnection" ), LFUNCVAL( net_createConnection ) },
{ LSTRKEY( "createUDPSocket" ), LFUNCVAL( net_createUDPSocket ) },
{ LSTRKEY( "multicastJoin"), LFUNCVAL( net_multicastJoin ) },
{ LSTRKEY( "multicastLeave"), LFUNCVAL( net_multicastLeave ) },
{ LSTRKEY( "dns" ), LROVAL( net_dns_map ) },
LROT_BEGIN(net_tcpserver)
LROT_FUNCENTRY( listen, net_listen )
LROT_FUNCENTRY( getaddr, net_getaddr )
LROT_FUNCENTRY( close, net_close )
LROT_FUNCENTRY( __gc, net_delete )
LROT_TABENTRY( __index, net_tcpserver )
LROT_END( net_tcpserver, net_tcpserver, 0 )
LROT_BEGIN(net_tcpsocket)
LROT_FUNCENTRY( connect, net_connect )
LROT_FUNCENTRY( close, net_close )
LROT_FUNCENTRY( on, net_on )
LROT_FUNCENTRY( send, net_send )
LROT_FUNCENTRY( hold, net_hold )
LROT_FUNCENTRY( unhold, net_unhold )
LROT_FUNCENTRY( dns, net_dns )
LROT_FUNCENTRY( ttl, net_ttl )
LROT_FUNCENTRY( getpeer, net_getpeer )
LROT_FUNCENTRY( getaddr, net_getaddr )
LROT_FUNCENTRY( __gc, net_delete )
LROT_TABENTRY( __index, net_tcpsocket )
LROT_END( net_tcpsocket, net_tcpsocket, 0 )
LROT_BEGIN(net_udpsocket)
LROT_FUNCENTRY( listen, net_listen )
LROT_FUNCENTRY( close, net_close )
LROT_FUNCENTRY( on, net_on )
LROT_FUNCENTRY( send, net_send )
LROT_FUNCENTRY( dns, net_dns )
LROT_FUNCENTRY( ttl, net_ttl )
LROT_FUNCENTRY( getaddr, net_getaddr )
LROT_FUNCENTRY( __gc, net_delete )
LROT_TABENTRY( __index, net_udpsocket )
LROT_END( net_udpsocket, net_udpsocket, 0 )
LROT_BEGIN(net_dns)
LROT_FUNCENTRY( setdnsserver, net_setdnsserver )
LROT_FUNCENTRY( getdnsserver, net_getdnsserver )
LROT_FUNCENTRY( resolve, net_dns_static )
LROT_END( net_dns, net_dns, 0 )
LROT_BEGIN(net)
LROT_FUNCENTRY( createServer, net_createServer )
LROT_FUNCENTRY( createConnection, net_createConnection )
LROT_FUNCENTRY( createUDPSocket, net_createUDPSocket )
LROT_FUNCENTRY( multicastJoin, net_multicastJoin )
LROT_FUNCENTRY( multicastLeave, net_multicastLeave )
LROT_TABENTRY( dns, net_dns )
#ifdef TLS_MODULE_PRESENT
{ LSTRKEY( "cert" ), LROVAL( tls_cert_map ) },
LROT_TABENTRY( cert, tls_cert )
#endif
{ LSTRKEY( "TCP" ), LNUMVAL( TYPE_TCP ) },
{ LSTRKEY( "UDP" ), LNUMVAL( TYPE_UDP ) },
{ LSTRKEY( "__metatable" ), LROVAL( net_map ) },
{ LNILKEY, LNILVAL }
};
LROT_NUMENTRY( TCP, TYPE_TCP )
LROT_NUMENTRY( UDP, TYPE_UDP )
LROT_TABENTRY( __metatable, net )
LROT_END( net, net, 0 )
int luaopen_net( lua_State *L ) {
igmp_init();
luaL_rometatable(L, NET_TABLE_TCP_SERVER, (void *)net_tcpserver_map);
luaL_rometatable(L, NET_TABLE_TCP_CLIENT, (void *)net_tcpsocket_map);
luaL_rometatable(L, NET_TABLE_UDP_SOCKET, (void *)net_udpsocket_map);
luaL_rometatable(L, NET_TABLE_TCP_SERVER, LROT_TABLEREF(net_tcpserver));
luaL_rometatable(L, NET_TABLE_TCP_CLIENT, LROT_TABLEREF(net_tcpsocket));
luaL_rometatable(L, NET_TABLE_UDP_SOCKET, LROT_TABLEREF(net_udpsocket));
return 0;
}
NODEMCU_MODULE(NET, "net", net_map, luaopen_net);
NODEMCU_MODULE(NET, "net", net, luaopen_net);
// Module for interfacing with system
#include "module.h"
#include "lauxlib.h"
......@@ -16,12 +15,9 @@
#include "lundump.h"
#include "platform.h"
#include "lrodefs.h"
#ifdef LUA_FLASH_STORE
#include "lflash.h"
#endif
#include "c_types.h"
#include "c_string.h"
#include <stdint.h>
#include <string.h>
#include "driver/uart.h"
#include "user_interface.h"
#include "flash_api.h"
......@@ -124,15 +120,71 @@ static int node_sleep( lua_State* L )
#endif //PMSLEEP_ENABLE
static int node_info( lua_State* L )
{
lua_pushinteger(L, NODE_VERSION_MAJOR);
lua_pushinteger(L, NODE_VERSION_MINOR);
lua_pushinteger(L, NODE_VERSION_REVISION);
lua_pushinteger(L, system_get_chip_id()); // chip id
lua_pushinteger(L, spi_flash_get_id()); // flash id
lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB
lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed());
return 8;
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_MINOR);
lua_pushinteger(L, NODE_VERSION_REVISION);
lua_pushinteger(L, system_get_chip_id()); // chip id
lua_pushinteger(L, spi_flash_get_id()); // flash id
lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB
lua_pushinteger(L, flash_rom_get_mode());
lua_pushinteger(L, flash_rom_get_speed());
return 8;
}
}
}
// Lua: chipid()
......@@ -162,10 +214,6 @@ static int node_flashid( lua_State* L )
// Lua: flashsize()
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();
lua_pushinteger( L, sz );
return 1;
......@@ -197,7 +245,7 @@ static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1;
void output_redirect(const char *str) {
lua_State *L = lua_getstate();
// if(c_strlen(str)>=TX_BUFF_SIZE){
// if(strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n");
// return;
// }
......@@ -268,18 +316,18 @@ static int node_compile( lua_State* L )
size_t len;
const char *fname = luaL_checklstring( L, 1, &len );
const char *basename = vfs_basename( fname );
luaL_argcheck(L, c_strlen(basename) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid");
luaL_argcheck(L, strlen(basename) <= FS_OBJ_NAME_LEN && strlen(fname) == len, 1, "filename invalid");
char *output = luaM_malloc( L, len+1 );
c_strcpy(output, fname);
strcpy(output, fname);
// 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 );
return luaL_error(L, "not a .lua file");
}
output[c_strlen(output) - 2] = 'c';
output[c_strlen(output) - 1] = '\0';
output[strlen(output) - 2] = 'c';
output[strlen(output) - 1] = '\0';
NODE_DBG(output);
NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) {
......@@ -578,68 +626,241 @@ static int node_random (lua_State *L) {
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
static const LUA_REG_TYPE node_egc_map[] = {
{ LSTRKEY( "meminfo" ), LFUNCVAL( node_egc_meminfo ) },
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) },
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
{ LSTRKEY( "ON_MEM_LIMIT" ), LNUMVAL( EGC_ON_MEM_LIMIT ) },
{ LSTRKEY( "ALWAYS" ), LNUMVAL( EGC_ALWAYS ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE node_task_map[] = {
{ LSTRKEY( "post" ), LFUNCVAL( node_task_post ) },
{ LSTRKEY( "LOW_PRIORITY" ), LNUMVAL( TASK_PRIORITY_LOW ) },
{ LSTRKEY( "MEDIUM_PRIORITY" ), LNUMVAL( TASK_PRIORITY_MEDIUM ) },
{ LSTRKEY( "HIGH_PRIORITY" ), LNUMVAL( TASK_PRIORITY_HIGH ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE node_map[] =
{
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
{ LSTRKEY( "info" ), LFUNCVAL( node_info ) },
{ LSTRKEY( "task" ), LROVAL( node_task_map ) },
#ifdef LUA_FLASH_STORE
{ LSTRKEY( "flashreload" ), LFUNCVAL( luaN_reload_reboot ) },
{ LSTRKEY( "flashindex" ), LFUNCVAL( luaN_index ) },
#endif
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
{ LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) },
{ LSTRKEY( "dsleepMax" ), LFUNCVAL( dsleepMax ) },
{ LSTRKEY( "sleep" ), LFUNCVAL( node_sleep ) },
LROT_BEGIN(node_egc)
LROT_FUNCENTRY( meminfo, node_egc_meminfo )
LROT_FUNCENTRY( setmode, node_egc_setmode )
LROT_NUMENTRY( NOT_ACTIVE, EGC_NOT_ACTIVE )
LROT_NUMENTRY( ON_ALLOC_FAILURE, EGC_ON_ALLOC_FAILURE )
LROT_NUMENTRY( ON_MEM_LIMIT, EGC_ON_MEM_LIMIT )
LROT_NUMENTRY( ALWAYS, EGC_ALWAYS )
LROT_END( node_egc, NULL, 0 )
LROT_BEGIN(node_task)
LROT_FUNCENTRY( post, node_task_post )
LROT_NUMENTRY( LOW_PRIORITY, TASK_PRIORITY_LOW )
LROT_NUMENTRY( MEDIUM_PRIORITY, TASK_PRIORITY_MEDIUM )
LROT_NUMENTRY( HIGH_PRIORITY, TASK_PRIORITY_HIGH )
LROT_END( node_task, NULL, 0 )
LROT_BEGIN(node)
LROT_FUNCENTRY( heap, node_heap )
LROT_FUNCENTRY( info, node_info )
LROT_TABENTRY( task, node_task )
LROT_FUNCENTRY( flashreload, luaN_reload_reboot )
LROT_FUNCENTRY( flashindex, luaN_index )
LROT_FUNCENTRY( restart, node_restart )
LROT_FUNCENTRY( dsleep, node_deepsleep )
LROT_FUNCENTRY( dsleepMax, dsleepMax )
LROT_FUNCENTRY( sleep, node_sleep )
#ifdef PMSLEEP_ENABLE
PMSLEEP_INT_MAP,
PMSLEEP_INT_MAP
#endif
{ LSTRKEY( "chipid" ), LFUNCVAL( node_chipid ) },
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
#ifdef DEVELOPMENT_TOOLS
LROT_FUNCENTRY( readrcr, node_readrcr )
LROT_FUNCENTRY( writercr, node_writercr )
#endif
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()
// { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) },
{ LSTRKEY( "compile" ), LFUNCVAL( node_compile) },
{ LSTRKEY( "CPU80MHZ" ), LNUMVAL( CPU80MHZ ) },
{ LSTRKEY( "CPU160MHZ" ), LNUMVAL( CPU160MHZ ) },
{ LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) },
{ LSTRKEY( "getcpufreq" ), LFUNCVAL( node_getcpufreq) },
{ LSTRKEY( "bootreason" ), LFUNCVAL( node_bootreason) },
{ LSTRKEY( "restore" ), LFUNCVAL( node_restore) },
{ LSTRKEY( "random" ), LFUNCVAL( node_random) },
// LROT_FUNCENTRY( readvdd33, node_readvdd33 )
LROT_FUNCENTRY( compile, node_compile )
LROT_NUMENTRY( CPU80MHZ, CPU80MHZ )
LROT_NUMENTRY( CPU160MHZ, CPU160MHZ )
LROT_FUNCENTRY( setcpufreq, node_setcpufreq )
LROT_FUNCENTRY( getcpufreq, node_getcpufreq )
LROT_FUNCENTRY( bootreason, node_bootreason )
LROT_FUNCENTRY( restore, node_restore )
LROT_FUNCENTRY( random, node_random )
#ifdef LUA_OPTIMIZE_DEBUG
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
LROT_FUNCENTRY( stripdebug, node_stripdebug )
#endif
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
LROT_TABENTRY( egc, node_egc )
#ifdef DEVELOPMENT_TOOLS
{ LSTRKEY( "osprint" ), LFUNCVAL( node_osprint ) },
LROT_FUNCENTRY( osprint, node_osprint )
#endif
LROT_FUNCENTRY( getpartitiontable, node_getpartitiontable )
LROT_FUNCENTRY( setpartitiontable, node_setpartitiontable )
// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
{ LNILKEY, LNILVAL }
};
// LROT_FUNCENTRY( dsleepsetoption, node_deepsleep_setoption )
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 )
#endif
// Module function map
static const LUA_REG_TYPE ow_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL( ow_setup ) },
{ LSTRKEY( "reset" ), LFUNCVAL( ow_reset ) },
{ LSTRKEY( "skip" ), LFUNCVAL( ow_skip ) },
{ LSTRKEY( "select" ), LFUNCVAL( ow_select ) },
{ LSTRKEY( "write" ), LFUNCVAL( ow_write ) },
{ LSTRKEY( "write_bytes" ), LFUNCVAL( ow_write_bytes ) },
{ LSTRKEY( "read" ), LFUNCVAL( ow_read ) },
{ LSTRKEY( "read_bytes" ), LFUNCVAL( ow_read_bytes ) },
{ LSTRKEY( "depower" ), LFUNCVAL( ow_depower ) },
LROT_BEGIN(ow)
LROT_FUNCENTRY( setup, ow_setup )
LROT_FUNCENTRY( reset, ow_reset )
LROT_FUNCENTRY( skip, ow_skip )
LROT_FUNCENTRY( select, ow_select )
LROT_FUNCENTRY( write, ow_write )
LROT_FUNCENTRY( write_bytes, ow_write_bytes )
LROT_FUNCENTRY( read, ow_read )
LROT_FUNCENTRY( read_bytes, ow_read_bytes )
LROT_FUNCENTRY( depower, ow_depower )
#if ONEWIRE_SEARCH
{ LSTRKEY( "reset_search" ), LFUNCVAL( ow_reset_search ) },
{ LSTRKEY( "target_search" ), LFUNCVAL( ow_target_search ) },
{ LSTRKEY( "search" ), LFUNCVAL( ow_search ) },
LROT_FUNCENTRY( reset_search, ow_reset_search )
LROT_FUNCENTRY( target_search, ow_target_search )
LROT_FUNCENTRY( search, ow_search )
#endif
#if ONEWIRE_CRC
{ LSTRKEY( "crc8" ), LFUNCVAL( ow_crc8 ) },
LROT_FUNCENTRY( crc8, ow_crc8 )
#if ONEWIRE_CRC16
{ LSTRKEY( "check_crc16" ), LFUNCVAL( ow_check_crc16 ) },
{ LSTRKEY( "crc16" ), LFUNCVAL( ow_crc16 ) },
LROT_FUNCENTRY( check_crc16, ow_check_crc16 )
LROT_FUNCENTRY( crc16, ow_crc16 )
#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 @@
#include "module.h"
#include "lauxlib.h"
#include "task/task.h"
#include "c_string.h"
#include "c_stdlib.h"
#include <string.h>
#include <stdlib.h>
#include "pcm.h"
#include "pcm_drv.h"
#include "pcm/pcm.h"
#include "pcm/pcm_drv.h"
#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 )
UNREF_CB( cfg->self_ref );
if (cfg->bufs[0].data) {
c_free( cfg->bufs[0].data );
free( cfg->bufs[0].data );
cfg->bufs[0].data = NULL;
}
if (cfg->bufs[1].data) {
c_free( cfg->bufs[1].data );
free( cfg->bufs[1].data );
cfg->bufs[1].data = NULL;
}
......@@ -152,19 +152,19 @@ static int pcm_drv_on( lua_State *L )
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);
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);
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);
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);
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);
cfg->cb_vu_ref = COND_REF( is_func );
......@@ -229,34 +229,34 @@ static int pcm_new( lua_State *L )
}
static const LUA_REG_TYPE pcm_driver_map[] = {
{ LSTRKEY( "play" ), LFUNCVAL( pcm_drv_play ) },
{ LSTRKEY( "pause" ), LFUNCVAL( pcm_drv_pause ) },
{ LSTRKEY( "stop" ), LFUNCVAL( pcm_drv_stop ) },
{ LSTRKEY( "close" ), LFUNCVAL( pcm_drv_close ) },
{ LSTRKEY( "on" ), LFUNCVAL( pcm_drv_on ) },
{ LSTRKEY( "__gc" ), LFUNCVAL( pcm_drv_free ) },
{ LSTRKEY( "__index" ), LROVAL( pcm_driver_map ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(pcm_driver)
LROT_FUNCENTRY( play, pcm_drv_play )
LROT_FUNCENTRY( pause, pcm_drv_pause )
LROT_FUNCENTRY( stop, pcm_drv_stop )
LROT_FUNCENTRY( close, pcm_drv_close )
LROT_FUNCENTRY( on, pcm_drv_on )
LROT_FUNCENTRY( __gc, pcm_drv_free )
LROT_TABENTRY( __index, pcm_driver )
LROT_END( pcm_driver, pcm_driver, LROT_MASK_GC_INDEX )
// Module function map
static const LUA_REG_TYPE pcm_map[] = {
{ LSTRKEY( "new" ), LFUNCVAL( pcm_new ) },
{ LSTRKEY( "SD" ), LNUMVAL( PCM_DRIVER_SD ) },
{ LSTRKEY( "RATE_1K" ), LNUMVAL( PCM_RATE_1K ) },
{ LSTRKEY( "RATE_2K" ), LNUMVAL( PCM_RATE_2K ) },
{ LSTRKEY( "RATE_4K" ), LNUMVAL( PCM_RATE_4K ) },
{ LSTRKEY( "RATE_5K" ), LNUMVAL( PCM_RATE_5K ) },
{ LSTRKEY( "RATE_8K" ), LNUMVAL( PCM_RATE_8K ) },
{ LSTRKEY( "RATE_10K" ), LNUMVAL( PCM_RATE_10K ) },
{ LSTRKEY( "RATE_12K" ), LNUMVAL( PCM_RATE_12K ) },
{ LSTRKEY( "RATE_16K" ), LNUMVAL( PCM_RATE_16K ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(pcm)
LROT_FUNCENTRY( new, pcm_new )
LROT_NUMENTRY( SD, PCM_DRIVER_SD )
LROT_NUMENTRY( RATE_1K, PCM_RATE_1K )
LROT_NUMENTRY( RATE_2K, PCM_RATE_2K )
LROT_NUMENTRY( RATE_4K, PCM_RATE_4K )
LROT_NUMENTRY( RATE_5K, PCM_RATE_5K )
LROT_NUMENTRY( RATE_8K, PCM_RATE_8K )
LROT_NUMENTRY( RATE_10K, PCM_RATE_10K )
LROT_NUMENTRY( RATE_12K, PCM_RATE_12K )
LROT_NUMENTRY( RATE_16K, PCM_RATE_16K )
LROT_END( pcm, NULL, 0 )
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_play_task = task_get_id( pcm_data_play );
......@@ -264,4 +264,4 @@ int luaopen_pcm( lua_State *L ) {
return 0;
}
NODEMCU_MODULE(PCM, "pcm", pcm_map, luaopen_pcm);
NODEMCU_MODULE(PCM, "pcm", pcm, luaopen_pcm);
......@@ -9,7 +9,7 @@
#include "ets_sys.h"
#include "os_type.h"
#include "osapi.h"
#include "c_stdlib.h"
#include <stdlib.h>
#include "module.h"
#include "lauxlib.h"
......@@ -135,10 +135,10 @@ static int perf_stop(lua_State *L)
return 4;
}
static const LUA_REG_TYPE perf_map[] = {
{ LSTRKEY( "start" ), LFUNCVAL( perf_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( perf_stop ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(perf)
LROT_FUNCENTRY( start, perf_start )
LROT_FUNCENTRY( stop, perf_stop )
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 @@
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_types.h"
#include <stdint.h>
// Lua: realfrequency = setup( id, frequency, duty )
static int lpwm_setup( lua_State* L )
......@@ -128,16 +128,16 @@ int lpwm_open( lua_State *L ) {
}
// Module function map
static const LUA_REG_TYPE pwm_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL( lpwm_setup ) },
{ LSTRKEY( "close" ), LFUNCVAL( lpwm_close ) },
{ LSTRKEY( "start" ), LFUNCVAL( lpwm_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( lpwm_stop ) },
{ LSTRKEY( "setclock" ), LFUNCVAL( lpwm_setclock ) },
{ LSTRKEY( "getclock" ), LFUNCVAL( lpwm_getclock ) },
{ LSTRKEY( "setduty" ), LFUNCVAL( lpwm_setduty ) },
{ LSTRKEY( "getduty" ), LFUNCVAL( lpwm_getduty ) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(PWM, "pwm", pwm_map, lpwm_open);
LROT_BEGIN(pwm)
LROT_FUNCENTRY( setup, lpwm_setup )
LROT_FUNCENTRY( close, lpwm_close )
LROT_FUNCENTRY( start, lpwm_start )
LROT_FUNCENTRY( stop, lpwm_stop )
LROT_FUNCENTRY( setclock, lpwm_setclock )
LROT_FUNCENTRY( getclock, lpwm_getclock )
LROT_FUNCENTRY( setduty, lpwm_setduty )
LROT_FUNCENTRY( getduty, lpwm_getduty )
LROT_END( pwm, NULL, 0 )
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) {
}
// Module function map
static const LUA_REG_TYPE rc_map[] = {
{ LSTRKEY( "send" ), LFUNCVAL( rc_send )},
{ LNILKEY, LNILVAL}
};
LROT_BEGIN(rc)
LROT_FUNCENTRY( send, rc_send )
LROT_END( rc, NULL, 0 )
int luaopen_rc(lua_State *L) {
// TODO: Make sure that the GPIO system is initialized
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 )
}
// Module function map
static const LUA_REG_TYPE rfswitch_map[] =
{
{ LSTRKEY( "send" ), LFUNCVAL( rfswitch_send ) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(rfswitch)
LROT_FUNCENTRY( send, rfswitch_send )
LROT_END( rfswitch, NULL, 0 )
NODEMCU_MODULE(RFSWITCH, "rfswitch", rfswitch_map, NULL);
NODEMCU_MODULE(RFSWITCH, "rfswitch", rfswitch, NULL);
......@@ -9,10 +9,10 @@
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "c_types.h"
#include <stdint.h>
#include <stdlib.h>
#include "user_interface.h"
#include "driver/rotary.h"
#include "../libc/c_stdlib.h"
#define MASK(x) (1 << ROTARY_ ## x ## _INDEX)
......@@ -145,7 +145,7 @@ static int lrotary_setup( lua_State* L )
callback_free(L, id, ROTARY_ALL);
if (!data[id]) {
data[id] = (DATA *) c_zalloc(sizeof(DATA));
data[id] = (DATA *) calloc(1, sizeof(DATA));
if (!data[id]) {
return -1;
}
......@@ -211,7 +211,7 @@ static int lrotary_close( lua_State* L )
DATA *d = data[id];
if (d) {
data[id] = NULL;
c_free(d);
free(d);
}
if (rotary_close( id )) {
......@@ -395,20 +395,20 @@ static int rotary_open(lua_State *L)
}
// Module function map
static const LUA_REG_TYPE rotary_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL( lrotary_setup ) },
{ LSTRKEY( "close" ), LFUNCVAL( lrotary_close ) },
{ LSTRKEY( "on" ), LFUNCVAL( lrotary_on ) },
{ LSTRKEY( "getpos" ), LFUNCVAL( lrotary_getpos) },
{ LSTRKEY( "TURN" ), LNUMVAL( MASK(TURN) ) },
{ LSTRKEY( "PRESS" ), LNUMVAL( MASK(PRESS) ) },
{ LSTRKEY( "RELEASE" ), LNUMVAL( MASK(RELEASE) ) },
{ LSTRKEY( "LONGPRESS" ),LNUMVAL( MASK(LONGPRESS) ) },
{ LSTRKEY( "CLICK" ), LNUMVAL( MASK(CLICK) ) },
{ LSTRKEY( "DBLCLICK" ), LNUMVAL( MASK(DBLCLICK)) },
{ LSTRKEY( "ALL" ), LNUMVAL( ROTARY_ALL ) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(ROTARY, "rotary", rotary_map, rotary_open);
LROT_BEGIN(rotary)
LROT_FUNCENTRY( setup, lrotary_setup )
LROT_FUNCENTRY( close, lrotary_close )
LROT_FUNCENTRY( on, lrotary_on )
LROT_FUNCENTRY( getpos, lrotary_getpos )
LROT_NUMENTRY( TURN, MASK(TURN) )
LROT_NUMENTRY( PRESS, MASK(PRESS) )
LROT_NUMENTRY( RELEASE, MASK(RELEASE) )
LROT_NUMENTRY( LONGPRESS, MASK(LONGPRESS) )
LROT_NUMENTRY( CLICK, MASK(CLICK) )
LROT_NUMENTRY( DBLCLICK, MASK(DBLCLICK) )
LROT_NUMENTRY( ALL, ROTARY_ALL )
LROT_END( rotary, NULL, 0 )
NODEMCU_MODULE(ROTARY, "rotary", rotary, rotary_open);
......@@ -6,6 +6,7 @@
#include "rtc/rtctime.h"
#define RTCTIME_SLEEP_ALIGNED rtctime_deep_sleep_until_aligned_us
#include "rtc/rtcfifo.h"
#include <string.h>
// rtcfifo.prepare ([{sensor_count=n, interval_us=m, storage_begin=x, storage_end=y}])
static int rtcfifo_prepare (lua_State *L)
......@@ -165,18 +166,18 @@ static int rtcfifo_dsleep_until_sample (lua_State *L)
#endif
// Module function map
static const LUA_REG_TYPE rtcfifo_map[] = {
{ LSTRKEY("prepare"), LFUNCVAL(rtcfifo_prepare) },
{ LSTRKEY("ready"), LFUNCVAL(rtcfifo_ready) },
{ LSTRKEY("put"), LFUNCVAL(rtcfifo_put) },
{ LSTRKEY("pop"), LFUNCVAL(rtcfifo_pop) },
{ LSTRKEY("peek"), LFUNCVAL(rtcfifo_peek) },
{ LSTRKEY("drop"), LFUNCVAL(rtcfifo_drop) },
{ LSTRKEY("count"), LFUNCVAL(rtcfifo_count) },
LROT_BEGIN(rtcfifo)
LROT_FUNCENTRY( prepare, rtcfifo_prepare )
LROT_FUNCENTRY( ready, rtcfifo_ready )
LROT_FUNCENTRY( put, rtcfifo_put )
LROT_FUNCENTRY( pop, rtcfifo_pop )
LROT_FUNCENTRY( peek, rtcfifo_peek )
LROT_FUNCENTRY( drop, rtcfifo_drop )
LROT_FUNCENTRY( count, rtcfifo_count )
#ifdef LUA_USE_MODULES_RTCTIME
{ LSTRKEY("dsleep_until_sample"), LFUNCVAL(rtcfifo_dsleep_until_sample) },
LROT_FUNCENTRY( dsleep_until_sample, rtcfifo_dsleep_until_sample )
#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)
// Module function map
static const LUA_REG_TYPE rtcmem_map[] = {
{ LSTRKEY("read32"), LFUNCVAL(rtcmem_read32) },
{ LSTRKEY("write32"), LFUNCVAL(rtcmem_write32) },
{ LNILKEY, LNILVAL }
};
LROT_BEGIN(rtcmem)
LROT_FUNCENTRY( read32, rtcmem_read32 )
LROT_FUNCENTRY( write32, rtcmem_write32 )
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
void rtctime_early_startup (void)
{
Cache_Read_Enable (0, 0, 1);
// Cache_Read_Enable (0, 0, 1);
rtc_time_register_bootup ();
rtc_time_switch_clocks ();
Cache_Read_Disable ();
// Cache_Read_Disable ();
}
void rtctime_late_startup (void)
......@@ -228,14 +228,14 @@ static int rtctime_epoch2cal (lua_State *L)
}
// Module function map
static const LUA_REG_TYPE rtctime_map[] = {
{ LSTRKEY("set"), LFUNCVAL(rtctime_set) },
{ LSTRKEY("get"), LFUNCVAL(rtctime_get) },
{ LSTRKEY("adjust_delta"), LFUNCVAL(rtctime_adjust_delta) },
{ LSTRKEY("dsleep"), LFUNCVAL(rtctime_dsleep) },
{ LSTRKEY("dsleep_aligned"), LFUNCVAL(rtctime_dsleep_aligned) },
{ LSTRKEY("epoch2cal"), LFUNCVAL(rtctime_epoch2cal) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(RTCTIME, "rtctime", rtctime_map, NULL);
LROT_BEGIN(rtctime)
LROT_FUNCENTRY( set, rtctime_set )
LROT_FUNCENTRY( get, rtctime_get )
LROT_FUNCENTRY( adjust_delta, rtctime_adjust_delta )
LROT_FUNCENTRY( dsleep, rtctime_dsleep )
LROT_FUNCENTRY( dsleep_aligned, rtctime_dsleep_aligned )
LROT_FUNCENTRY( epoch2cal, rtctime_epoch2cal )
LROT_END( rtctime, NULL, 0 )
NODEMCU_MODULE(RTCTIME, "rtctime", rtctime, NULL);
......@@ -247,19 +247,19 @@ static int si7021_lua_firmware(lua_State* L) {
return 1;
}
static const LUA_REG_TYPE si7021_map[] = {
{ LSTRKEY( "setup" ), LFUNCVAL(si7021_lua_setup) },
{ LSTRKEY( "setting" ), LFUNCVAL(si7021_lua_setting) },
{ LSTRKEY( "read" ), LFUNCVAL(si7021_lua_read) },
{ LSTRKEY( "serial" ), LFUNCVAL(si7021_lua_serial) },
{ LSTRKEY( "firmware" ), LFUNCVAL(si7021_lua_firmware) },
{ LSTRKEY( "RH12_TEMP14" ), LNUMVAL(SI7021_RH12_TEMP14) },
{ LSTRKEY( "RH08_TEMP12" ), LNUMVAL(SI7021_RH08_TEMP12) },
{ LSTRKEY( "RH10_TEMP13" ), LNUMVAL(SI7021_RH10_TEMP13) },
{ LSTRKEY( "RH11_TEMP11" ), LNUMVAL(SI7021_RH11_TEMP11) },
{ LSTRKEY( "HEATER_ENABLE" ), LNUMVAL(SI7021_HEATER_ENABLE) },
{ LSTRKEY( "HEATER_DISABLE" ), LNUMVAL(SI7021_HEATER_DISABLE) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SI7021, "si7021", si7021_map, NULL);
LROT_BEGIN(si7021)
LROT_FUNCENTRY( setup, si7021_lua_setup )
LROT_FUNCENTRY( setting, si7021_lua_setting )
LROT_FUNCENTRY( read, si7021_lua_read )
LROT_FUNCENTRY( serial, si7021_lua_serial )
LROT_FUNCENTRY( firmware, si7021_lua_firmware )
LROT_NUMENTRY( RH12_TEMP14, SI7021_RH12_TEMP14 )
LROT_NUMENTRY( RH08_TEMP12, SI7021_RH08_TEMP12 )
LROT_NUMENTRY( RH10_TEMP13, SI7021_RH10_TEMP13 )
LROT_NUMENTRY( RH11_TEMP11, SI7021_RH11_TEMP11 )
LROT_NUMENTRY( HEATER_ENABLE, SI7021_HEATER_ENABLE )
LROT_NUMENTRY( HEATER_DISABLE, SI7021_HEATER_DISABLE )
LROT_END( si7021, NULL, 0 )
NODEMCU_MODULE(SI7021, "si7021", si7021, NULL);
......@@ -74,14 +74,13 @@ static int sigma_delta_settarget( lua_State *L )
// Module function map
static const LUA_REG_TYPE sigma_delta_map[] =
{
{ LSTRKEY( "setup" ), LFUNCVAL( sigma_delta_setup ) },
{ LSTRKEY( "close" ), LFUNCVAL( sigma_delta_close ) },
{ LSTRKEY( "setpwmduty" ), LFUNCVAL( sigma_delta_setpwmduty ) },
{ LSTRKEY( "setprescale" ), LFUNCVAL( sigma_delta_setprescale ) },
{ LSTRKEY( "settarget" ), LFUNCVAL( sigma_delta_settarget ) },
{ LNILKEY, LNILVAL }
};
NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta_map, NULL);
LROT_BEGIN(sigma_delta)
LROT_FUNCENTRY( setup, sigma_delta_setup )
LROT_FUNCENTRY( close, sigma_delta_close )
LROT_FUNCENTRY( setpwmduty, sigma_delta_setpwmduty )
LROT_FUNCENTRY( setprescale, sigma_delta_setprescale )
LROT_FUNCENTRY( settarget, sigma_delta_settarget )
LROT_END( sigma_delta, NULL, 0 )
NODEMCU_MODULE(SIGMA_DELTA, "sigma_delta", sigma_delta, NULL);
......@@ -6,13 +6,13 @@
#ifndef LOCAL_LUA
#include "module.h"
#include "c_string.h"
#include "c_math.h"
#include "c_limits.h"
#include <string.h>
#include <math.h>
#include <limits.h>
#endif
#include "json_config.h"
#include "jsonsl.h"
#include "sjson/json_config.h"
#include "sjson/jsonsl.h"
#define LUA_SJSONLIBNAME "sjson"
......@@ -992,74 +992,33 @@ static int sjson_encoder_destructor(lua_State *L) {
return 0;
}
#ifdef LOCAL_LUA
static const luaL_Reg sjson_encoder_map[] = {
{ "read", sjson_encoder_read },
{ "__gc", sjson_encoder_destructor },
{ NULL, NULL }
};
static const luaL_Reg sjson_decoder_map[] = {
{ "write", sjson_decoder_write },
{ "result", sjson_decoder_result },
{ "__gc", sjson_decoder_destructor },
{ NULL, NULL }
};
static const luaL_Reg sjsonlib[] = {
{ "decode", sjson_decode },
{ "decoder", sjson_decoder },
{ "encode", sjson_encode },
{ "encoder", sjson_encoder },
{NULL, NULL}
};
#else
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
LROT_BEGIN(sjson_encoder)
LROT_FUNCENTRY( read, sjson_encoder_read )
LROT_FUNCENTRY( __gc, sjson_encoder_destructor )
LROT_TABENTRY( __index, sjson_encoder )
LROT_END( sjson_encoder, sjson_encoder, LROT_MASK_GC_INDEX )
LROT_BEGIN(sjson_decoder)
LROT_FUNCENTRY( write, sjson_decoder_write )
LROT_FUNCENTRY( result, sjson_decoder_result )
LROT_FUNCENTRY( __gc, sjson_decoder_destructor )
LROT_TABENTRY( __index, sjson_decoder )
LROT_END( sjson_decoder, sjson_decoder, LROT_MASK_GC_INDEX )
LROT_BEGIN(sjson)
LROT_FUNCENTRY( encode, sjson_encode )
LROT_FUNCENTRY( decode, sjson_decode )
LROT_FUNCENTRY( encoder, sjson_encoder )
LROT_FUNCENTRY( decoder, sjson_decoder )
LROT_LUDENTRY( NULL, 0 )
LROT_END( sjson, NULL, 0 )
LUALIB_API int luaopen_sjson (lua_State *L) {
#ifdef LOCAL_LUA
luaL_register(L, LUA_SJSONLIBNAME, sjsonlib);
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
luaL_rometatable(L, "sjson.decoder", LROT_TABLEREF(sjson_decoder));
luaL_rometatable(L, "sjson.encoder", LROT_TABLEREF(sjson_encoder));
return 1;
}
#ifndef LOCAL_LUA
NODEMCU_MODULE(SJSON, "sjson", sjson_map, luaopen_sjson);
#endif
NODEMCU_MODULE(SJSON, "sjson", sjson, luaopen_sjson);
......@@ -38,7 +38,9 @@
#include "os_type.h"
#include "osapi.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 "lwip/dns.h"
#include "task/task.h"
......@@ -48,6 +50,8 @@
#include "rtc/rtctime.h"
#endif
struct netif * eagle_lwip_getif(uint8 index);
#define max(a,b) ((a < b) ? b : a)
#define NTP_PORT 123
......@@ -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->err_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
os_free (state);
free (state);
state = 0;
}
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) {
memcpy(temp, serverp, server_count * sizeof(ip_addr_t));
}
if (serverp) {
c_free(serverp);
free(serverp);
}
serverp = temp;
......@@ -623,7 +627,7 @@ static void sntp_dolookups (lua_State *L) {
// 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,
// 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();
return;
}
......@@ -671,7 +675,7 @@ static void sntp_dolookups (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)
return ("out of memory");
......@@ -698,9 +702,17 @@ static char *state_init(lua_State *L) {
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) {
set_repeat_mode(L, FALSE);
repeat = (sntp_repeat_t *) c_malloc(sizeof(sntp_repeat_t));
repeat = (sntp_repeat_t *) malloc(sizeof(sntp_repeat_t));
if (!repeat) {
return "no memory";
}
......@@ -716,16 +728,8 @@ static char *set_repeat_mode(lua_State *L, bool enable)
//The function on_long_timeout returns errors to the developer
//My guess: Error reporting is a good thing, resume the timer.
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;
}
......@@ -787,43 +791,43 @@ static int sntp_sync (lua_State *L)
if (lua_istable(L, 1)) {
// Save a reference to the table
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 {
size_t l;
const char *hostname = luaL_checklstring(L, 1, &l);
if (l>128 || hostname == NULL)
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) {
// default to ntp pool
lua_newtable(L);
int i;
for (i = 0; i < 4; i++) {
lua_pushnumber(L, i + 1);
char buf[64];
c_sprintf(buf, "%d.nodemcu.pool.ntp.org", i);
lua_pushstring(L, buf);
lua_settable(L, -3);
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;
for (i = 0; i < 4; i++) {
lua_pushnumber(L, i + 1);
char buf[64];
sprintf(buf, "%d.nodemcu.pool.ntp.org", i);
lua_pushstring(L, buf);
lua_settable(L, -3);
}
}
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
state->list_ref = luaL_ref(L, LUA_REGISTRYINDEX);
sntp_dolookups(L);
goto good_ret;
}
sntp_dosend ();
luaL_unref (L, LUA_REGISTRYINDEX, state->list_ref);
state->list_ref = luaL_ref(L, LUA_REGISTRYINDEX);
sntp_dolookups(L);
good_ret:
if (!lua_isnoneornil(L, 4)) {
set_repeat_mode(L, 1);
}
......@@ -835,7 +839,7 @@ error:
{
if (state->pcb)
udp_remove (state->pcb);
c_free (state);
free (state);
state = 0;
}
return luaL_error (L, errmsg);
......@@ -869,13 +873,13 @@ static int sntp_open(lua_State *L)
// Module function map
static const LUA_REG_TYPE sntp_map[] = {
{ LSTRKEY("sync"), LFUNCVAL(sntp_sync) },
LROT_BEGIN(sntp)
LROT_FUNCENTRY( sync, sntp_sync )
#ifdef LUA_USE_MODULES_RTCTIME
{ LSTRKEY("setoffset"), LFUNCVAL(sntp_setoffset) },
{ LSTRKEY("getoffset"), LFUNCVAL(sntp_getoffset) },
LROT_FUNCENTRY( setoffset, sntp_setoffset )
LROT_FUNCENTRY( getoffset, sntp_getoffset )
#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