2016-05-26 10:36:20 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
2015-02-04 18:32:57 +01:00
|
|
|
#include "coap.h"
|
|
|
|
|
|
|
|
#include "lua.h"
|
|
|
|
#include "lauxlib.h"
|
|
|
|
#include "lualib.h"
|
|
|
|
|
|
|
|
#include "os_type.h"
|
2015-10-08 05:14:51 +02:00
|
|
|
#include "user_interface.h"
|
|
|
|
#include "user_config.h"
|
2015-02-04 18:32:57 +01:00
|
|
|
|
2015-03-15 13:12:29 +01:00
|
|
|
void build_well_known_rsp(char *rsp, uint16_t rsplen);
|
2015-02-04 18:32:57 +01:00
|
|
|
|
|
|
|
void endpoint_setup(void)
|
|
|
|
{
|
|
|
|
coap_setup();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}};
|
|
|
|
static int handle_get_well_known_core(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
|
|
|
{
|
2016-05-26 10:36:20 +02:00
|
|
|
outpkt->content.p = (uint8_t *)zalloc(MAX_PAYLOAD_SIZE); // this should be free-ed when outpkt is built in coap_server_respond()
|
2015-03-15 13:12:29 +01:00
|
|
|
if(outpkt->content.p == NULL){
|
|
|
|
NODE_DBG("not enough memory\n");
|
|
|
|
return COAP_ERR_BUFFER_TOO_SMALL;
|
|
|
|
}
|
|
|
|
outpkt->content.len = MAX_PAYLOAD_SIZE;
|
|
|
|
build_well_known_rsp(outpkt->content.p, outpkt->content.len);
|
2016-05-26 10:36:20 +02:00
|
|
|
return coap_make_response(scratch, outpkt, (const uint8_t *)outpkt->content.p, strlen(outpkt->content.p), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT);
|
2015-02-04 18:32:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static const coap_endpoint_path_t path_variable = {2, {"v1", "v"}};
|
|
|
|
static int handle_get_variable(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
|
|
|
{
|
|
|
|
const coap_option_t *opt;
|
|
|
|
uint8_t count;
|
2015-03-15 06:44:50 +01:00
|
|
|
int n;
|
2015-02-04 18:32:57 +01:00
|
|
|
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count)))
|
|
|
|
{
|
|
|
|
if ((count != ep->path->count ) && (count != ep->path->count + 1)) // +1 for /f/[function], /v/[variable]
|
|
|
|
{
|
|
|
|
NODE_DBG("should never happen.\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (count == ep->path->count + 1)
|
|
|
|
{
|
|
|
|
coap_luser_entry *h = ep->user_entry->next; // ->next: skip the first entry(head)
|
|
|
|
while(NULL != h){
|
2016-05-26 10:36:20 +02:00
|
|
|
if (opt[count-1].buf.len != strlen(h->name))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
|
|
|
h = h->next;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-26 10:36:20 +02:00
|
|
|
if (0 == memcmp(h->name, opt[count-1].buf.p, opt[count-1].buf.len))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
|
|
|
NODE_DBG("/v1/v/");
|
2015-02-07 16:08:25 +01:00
|
|
|
NODE_DBG((char *)h->name);
|
2015-02-04 18:32:57 +01:00
|
|
|
NODE_DBG(" match.\n");
|
|
|
|
if(h->L == NULL)
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
2016-05-26 10:36:20 +02:00
|
|
|
if(strlen(h->name))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
2015-03-15 06:44:50 +01:00
|
|
|
n = lua_gettop(h->L);
|
2015-02-04 18:32:57 +01:00
|
|
|
lua_getglobal(h->L, h->name);
|
2015-11-09 09:21:39 +01:00
|
|
|
if (!lua_isnumber(h->L, -1) && !lua_isstring(h->L, -1)) {
|
|
|
|
NODE_DBG ("should be a number or string.\n");
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2015-02-04 18:32:57 +01:00
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
|
|
|
} else {
|
|
|
|
const char *res = lua_tostring(h->L,-1);
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2016-05-26 10:36:20 +02:00
|
|
|
return coap_make_response(scratch, outpkt, (const uint8_t *)res, strlen(res), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, h->content_type);
|
2015-02-04 18:32:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
h = h->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
NODE_DBG("/v1/v match.\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NODE_DBG("none match.\n");
|
|
|
|
end:
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const coap_endpoint_path_t path_function = {2, {"v1", "f"}};
|
|
|
|
static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
|
|
|
{
|
|
|
|
const coap_option_t *opt;
|
|
|
|
uint8_t count;
|
2015-03-15 06:44:50 +01:00
|
|
|
int n;
|
2015-02-04 18:32:57 +01:00
|
|
|
if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count)))
|
|
|
|
{
|
|
|
|
if ((count != ep->path->count ) && (count != ep->path->count + 1)) // +1 for /f/[function], /v/[variable]
|
|
|
|
{
|
|
|
|
NODE_DBG("should never happen.\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (count == ep->path->count + 1)
|
|
|
|
{
|
|
|
|
coap_luser_entry *h = ep->user_entry->next; // ->next: skip the first entry(head)
|
|
|
|
while(NULL != h){
|
2016-05-26 10:36:20 +02:00
|
|
|
if (opt[count-1].buf.len != strlen(h->name))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
|
|
|
h = h->next;
|
|
|
|
continue;
|
|
|
|
}
|
2016-05-26 10:36:20 +02:00
|
|
|
if (0 == memcmp(h->name, opt[count-1].buf.p, opt[count-1].buf.len))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
|
|
|
NODE_DBG("/v1/f/");
|
2015-02-07 16:08:25 +01:00
|
|
|
NODE_DBG((char *)h->name);
|
2015-02-04 18:32:57 +01:00
|
|
|
NODE_DBG(" match.\n");
|
|
|
|
|
|
|
|
if(h->L == NULL)
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
if(strlen(h->name))
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
2015-03-15 06:44:50 +01:00
|
|
|
n = lua_gettop(h->L);
|
2015-02-04 18:32:57 +01:00
|
|
|
lua_getglobal(h->L, h->name);
|
|
|
|
if (lua_type(h->L, -1) != LUA_TFUNCTION) {
|
|
|
|
NODE_DBG ("should be a function\n");
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2015-02-04 18:32:57 +01:00
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
|
|
|
} else {
|
|
|
|
lua_pushlstring(h->L, inpkt->payload.p, inpkt->payload.len); // make sure payload.p is filled with '\0' after payload.len, or use lua_pushlstring
|
|
|
|
lua_call(h->L, 1, 1);
|
|
|
|
if (!lua_isnil(h->L, -1)){ /* get return? */
|
|
|
|
if( lua_isstring(h->L, -1) ) // deal with the return string
|
|
|
|
{
|
|
|
|
size_t len = 0;
|
|
|
|
const char *ret = luaL_checklstring( h->L, -1, &len );
|
|
|
|
if(len > MAX_PAYLOAD_SIZE){
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2015-02-04 18:32:57 +01:00
|
|
|
luaL_error( h->L, "return string:<MAX_PAYLOAD_SIZE" );
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
|
|
|
}
|
2015-02-07 16:08:25 +01:00
|
|
|
NODE_DBG((char *)ret);
|
2015-02-04 18:32:57 +01:00
|
|
|
NODE_DBG("\n");
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2015-02-04 18:32:57 +01:00
|
|
|
return coap_make_response(scratch, outpkt, ret, len, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
}
|
|
|
|
} else {
|
2015-03-15 06:44:50 +01:00
|
|
|
lua_settop(h->L, n);
|
2015-02-04 18:32:57 +01:00
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
h = h->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
NODE_DBG("/v1/f match.\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NODE_DBG("none match.\n");
|
|
|
|
end:
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern lua_Load gLoad;
|
|
|
|
static const coap_endpoint_path_t path_command = {2, {"v1", "c"}};
|
|
|
|
static int handle_post_command(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
|
|
|
{
|
|
|
|
if (inpkt->payload.len == 0)
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
if (inpkt->payload.len > 0)
|
|
|
|
{
|
|
|
|
lua_Load *load = &gLoad;
|
|
|
|
if(load->line_position == 0){
|
|
|
|
coap_buffer_to_string(load->line, load->len,&inpkt->payload);
|
2016-05-26 10:36:20 +02:00
|
|
|
load->line_position = strlen(load->line)+1;
|
2015-02-04 18:32:57 +01:00
|
|
|
// load->line[load->line_position-1] = '\n';
|
|
|
|
// load->line[load->line_position] = 0;
|
|
|
|
// load->line_position++;
|
|
|
|
load->done = 1;
|
|
|
|
NODE_DBG("Get command:\n");
|
|
|
|
NODE_DBG(load->line); // buggy here
|
|
|
|
NODE_DBG("\nResult(if any):\n");
|
Initial pass at switching to RTOS SDK.
This compiles, links, and starts the RTOS without crashing and burning.
Lua environment does not yet start due to the different task architecture.
Known pain points:
- task implementation needs to be rewritten for RTOS (next up on my TODO)
- secure espconn does not exist, all secure espconn stuff has been #if 0'd
- lwip now built from within the RTOS SDK, but does not appear to include
MDNS support. Investigation needed.
- there is no access to FRC1 NMI, not sure if we ever actually used that
however. Also #if 0'd out for now.
- new timing constraints introduced by the RTOS, all use of ets_delay_us()
and os_delay_us() needs to be reviewed (the tsl2561 driver in particular).
- even more confusion with ets_ vs os_ vs c_ vs non-prefixed versions.
In the long run everything should be switched to non-prefixed versions.
- system_set_os_print() not available, needs to be reimplemented
- all the RTOS rodata is loaded into RAM, as it apparently uses some
constants while the flash isn't mapped, so our exception handler can't
work its magic. This should be narrowed down to the minimum possible
at some point.
- with each task having its own stack in RTOS, we probably need change
flash-page buffers from the stack to the heap in a bunch of places.
A single, shared, page buffer *might* be possible if we limit ourselves
to running NodeMCU in a single task.
- there's a ton of junk in the sdk-overrides now; over time the core code
should be updated to not need those shims
2016-05-24 07:05:01 +02:00
|
|
|
#if 0 // FIXME
|
2015-10-08 05:14:51 +02:00
|
|
|
system_os_post (LUA_TASK_PRIO, LUA_PROCESS_LINE_SIG, 0);
|
Initial pass at switching to RTOS SDK.
This compiles, links, and starts the RTOS without crashing and burning.
Lua environment does not yet start due to the different task architecture.
Known pain points:
- task implementation needs to be rewritten for RTOS (next up on my TODO)
- secure espconn does not exist, all secure espconn stuff has been #if 0'd
- lwip now built from within the RTOS SDK, but does not appear to include
MDNS support. Investigation needed.
- there is no access to FRC1 NMI, not sure if we ever actually used that
however. Also #if 0'd out for now.
- new timing constraints introduced by the RTOS, all use of ets_delay_us()
and os_delay_us() needs to be reviewed (the tsl2561 driver in particular).
- even more confusion with ets_ vs os_ vs c_ vs non-prefixed versions.
In the long run everything should be switched to non-prefixed versions.
- system_set_os_print() not available, needs to be reimplemented
- all the RTOS rodata is loaded into RAM, as it apparently uses some
constants while the flash isn't mapped, so our exception handler can't
work its magic. This should be narrowed down to the minimum possible
at some point.
- with each task having its own stack in RTOS, we probably need change
flash-page buffers from the stack to the heap in a bunch of places.
A single, shared, page buffer *might* be possible if we limit ourselves
to running NodeMCU in a single task.
- there's a ton of junk in the sdk-overrides now; over time the core code
should be updated to not need those shims
2016-05-24 07:05:01 +02:00
|
|
|
#endif
|
2015-02-04 18:32:57 +01:00
|
|
|
}
|
|
|
|
return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t id = 0;
|
|
|
|
static const coap_endpoint_path_t path_id = {2, {"v1", "id"}};
|
|
|
|
static int handle_get_id(const coap_endpoint_t *ep, coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo)
|
|
|
|
{
|
|
|
|
id = system_get_chip_id();
|
|
|
|
return coap_make_response(scratch, outpkt, (const uint8_t *)(&id), sizeof(uint32_t), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
|
|
|
|
}
|
|
|
|
|
2015-11-09 09:21:39 +01:00
|
|
|
coap_luser_entry var_head = {NULL,NULL,NULL,0};
|
2015-02-04 18:32:57 +01:00
|
|
|
coap_luser_entry *variable_entry = &var_head;
|
|
|
|
|
2015-11-09 09:21:39 +01:00
|
|
|
coap_luser_entry func_head = {NULL,NULL,NULL,0};
|
2015-02-04 18:32:57 +01:00
|
|
|
coap_luser_entry *function_entry = &func_head;
|
|
|
|
|
|
|
|
const coap_endpoint_t endpoints[] =
|
|
|
|
{
|
|
|
|
{COAP_METHOD_GET, handle_get_well_known_core, &path_well_known_core, "ct=40", NULL},
|
|
|
|
{COAP_METHOD_GET, handle_get_variable, &path_variable, "ct=0", &var_head},
|
|
|
|
{COAP_METHOD_POST, handle_post_function, &path_function, NULL, &func_head},
|
|
|
|
{COAP_METHOD_POST, handle_post_command, &path_command, NULL, NULL},
|
|
|
|
{COAP_METHOD_GET, handle_get_id, &path_id, "ct=0", NULL},
|
|
|
|
{(coap_method_t)0, NULL, NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2015-03-15 13:12:29 +01:00
|
|
|
void build_well_known_rsp(char *rsp, uint16_t rsplen)
|
2015-02-04 18:32:57 +01:00
|
|
|
{
|
|
|
|
const coap_endpoint_t *ep = endpoints;
|
|
|
|
int i;
|
|
|
|
uint16_t len = rsplen;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
memset(rsp, 0, len);
|
2015-02-04 18:32:57 +01:00
|
|
|
|
|
|
|
len--; // Null-terminated string
|
|
|
|
|
|
|
|
while(NULL != ep->handler)
|
|
|
|
{
|
|
|
|
if (NULL == ep->core_attr) {
|
|
|
|
ep++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (NULL == ep->user_entry){
|
2016-05-26 10:36:20 +02:00
|
|
|
if (0 < strlen(rsp)) {
|
|
|
|
strncat(rsp, ",", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, "<", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
|
|
|
|
for (i = 0; i < ep->path->count; i++) {
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, "/", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ep->path->elems[i], len);
|
|
|
|
len -= strlen(ep->path->elems[i]);
|
2015-02-04 18:32:57 +01:00
|
|
|
}
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ">;", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len -= 2;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ep->core_attr, len);
|
|
|
|
len -= strlen(ep->core_attr);
|
2015-02-04 18:32:57 +01:00
|
|
|
} else {
|
|
|
|
coap_luser_entry *h = ep->user_entry->next; // ->next: skip the first entry(head)
|
|
|
|
while(NULL != h){
|
2016-05-26 10:36:20 +02:00
|
|
|
if (0 < strlen(rsp)) {
|
|
|
|
strncat(rsp, ",", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, "<", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
|
|
|
|
for (i = 0; i < ep->path->count; i++) {
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, "/", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ep->path->elems[i], len);
|
|
|
|
len -= strlen(ep->path->elems[i]);
|
2015-02-04 18:32:57 +01:00
|
|
|
}
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, "/", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len--;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, h->name, len);
|
|
|
|
len -= strlen(h->name);
|
2015-02-04 18:32:57 +01:00
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ">;", len);
|
2015-02-04 18:32:57 +01:00
|
|
|
len -= 2;
|
|
|
|
|
2016-05-26 10:36:20 +02:00
|
|
|
strncat(rsp, ep->core_attr, len);
|
|
|
|
len -= strlen(ep->core_attr);
|
2015-02-04 18:32:57 +01:00
|
|
|
|
|
|
|
h = h->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ep++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|