new SLIP protocol; basic REST working

pull/95/head
Thorsten von Eicken 9 years ago
parent 109c10c3f2
commit 5a891c3c1e
  1. 114
      cmd/cmd.c
  2. 57
      cmd/cmd.h
  3. 160
      cmd/handlers.c
  4. 128
      mqtt/mqtt_cmd.c
  5. 12
      mqtt/mqtt_cmd.h
  6. 143
      rest/rest.c
  7. 29
      rest/rest.h
  8. 2
      serial/slip.c

@ -9,13 +9,6 @@
#ifdef CMD_DBG #ifdef CMD_DBG
#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
static const char *cmd_names[] = {
"NULL", "RESET", "IS_READY", "WIFI_CONNECT",
"MQTT_SETUP", "MQTT_CONNECT", "MQTT_DISCONNECT",
"MQTT_PUBLISH", "MQTT_SUBSCRIBE", "MQTT_LWT", "MQTT_EVENTS",
"REST_SETUP", "REST_REQUEST", "REST_SETHEADER", "REST_EVENTS",
"CB_ADD", "CB_EVENTS",
};
#else #else
#define DBG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
@ -25,7 +18,7 @@ extern const CmdList commands[];
//===== ESP -> Serial responses //===== ESP -> Serial responses
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_ProtoWrite(uint8_t data) { cmdProtoWrite(uint8_t data) {
switch(data){ switch(data){
case SLIP_END: case SLIP_END:
uart0_write_char(SLIP_ESC); uart0_write_char(SLIP_ESC);
@ -41,98 +34,83 @@ CMD_ProtoWrite(uint8_t data) {
} }
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_ProtoWriteBuf(uint8_t *data, short len) { cmdProtoWriteBuf(uint8_t *data, short len) {
while (len--) CMD_ProtoWrite(*data++); while (len--) cmdProtoWrite(*data++);
} }
static uint16_t resp_crc;
// Start a response, returns the partial CRC // Start a response, returns the partial CRC
uint16_t ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_ResponseStart(uint16_t cmd, uint32_t callback, uint32_t _return, uint16_t argc) { cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc) {
uint16_t crc = 0; DBG("cmdResponse: cmd=%d val=%ld argc=%d\n", cmd, value, argc);
uart0_write_char(SLIP_END); uart0_write_char(SLIP_END);
CMD_ProtoWriteBuf((uint8_t*)&cmd, 2); cmdProtoWriteBuf((uint8_t*)&cmd, 2);
crc = crc16_data((uint8_t*)&cmd, 2, crc); resp_crc = crc16_data((uint8_t*)&cmd, 2, 0);
CMD_ProtoWriteBuf((uint8_t*)&callback, 4); cmdProtoWriteBuf((uint8_t*)&argc, 2);
crc = crc16_data((uint8_t*)&callback, 4, crc); resp_crc = crc16_data((uint8_t*)&argc, 2, resp_crc);
CMD_ProtoWriteBuf((uint8_t*)&_return, 4); cmdProtoWriteBuf((uint8_t*)&value, 4);
crc = crc16_data((uint8_t*)&_return, 4, crc); resp_crc = crc16_data((uint8_t*)&value, 4, resp_crc);
CMD_ProtoWriteBuf((uint8_t*)&argc, 2);
crc = crc16_data((uint8_t*)&argc, 2, crc);
return crc;
} }
// Adds data to a response, returns the partial CRC // Adds data to a response, returns the partial CRC
uint16_t ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_ResponseBody(uint16_t crc_in, uint8_t* data, short len) { cmdResponseBody(void *data, uint16_t len) {
short pad_len = len+3 - (len+3)%4; // round up to multiple of 4 cmdProtoWriteBuf((uint8_t*)&len, 2);
CMD_ProtoWriteBuf((uint8_t*)&pad_len, 2); resp_crc = crc16_data((uint8_t*)&len, 2, resp_crc);
crc_in = crc16_data((uint8_t*)&pad_len, 2, crc_in);
CMD_ProtoWriteBuf(data, len); cmdProtoWriteBuf(data, len);
crc_in = crc16_data(data, len, crc_in); resp_crc = crc16_data(data, len, resp_crc);
if (pad_len > len) { uint16_t pad = (4-(len&3))&3; // get to multiple of 4
if (pad > 0) {
uint32_t temp = 0; uint32_t temp = 0;
CMD_ProtoWriteBuf((uint8_t*)&temp, pad_len-len); cmdProtoWriteBuf((uint8_t*)&temp, pad);
crc_in = crc16_data((uint8_t*)&temp, pad_len-len, crc_in); resp_crc = crc16_data((uint8_t*)&temp, pad, resp_crc);
} }
return crc_in;
} }
// Ends a response // Ends a response
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_ResponseEnd(uint16_t crc) { cmdResponseEnd() {
CMD_ProtoWriteBuf((uint8_t*)&crc, 2); cmdProtoWriteBuf((uint8_t*)&resp_crc, 2);
uart0_write_char(SLIP_END); uart0_write_char(SLIP_END);
} }
//===== serial -> ESP commands //===== serial -> ESP commands
// Execute a parsed command // Execute a parsed command
static uint32_t ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_Exec(const CmdList *scp, CmdPacket *packet) { cmdExec(const CmdList *scp, CmdPacket *packet) {
uint16_t crc = 0;
// Iterate through the command table and call the appropriate function // Iterate through the command table and call the appropriate function
while (scp->sc_function != NULL) { while (scp->sc_function != NULL) {
if(scp->sc_name == packet->cmd) { if(scp->sc_name == packet->cmd) {
DBG("CMD_Exec: Dispatching cmd=%s\n", cmd_names[packet->cmd]); DBG("cmdExec: Dispatching cmd=%s\n", scp->sc_text);
// call command function // call command function
uint32_t ret = scp->sc_function(packet); scp->sc_function(packet);
// if requestor asked for a response, send it return;
if (packet->_return){
DBG("CMD_Exec: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd);
crc = CMD_ResponseStart(packet->cmd, 0, ret, 0);
CMD_ResponseEnd(crc);
} else {
DBG("CMD_Exec: no response (%lu)\n", packet->_return);
}
return ret;
} }
scp++; scp++;
} }
DBG("CMD_Exec: cmd=%d not found\n", packet->cmd); DBG("cmdExec: cmd=%d not found\n", packet->cmd);
return 0;
} }
// Parse a packet and print info about it // Parse a packet and print info about it
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_parse_packet(uint8_t *buf, short len) { cmdParsePacket(uint8_t *buf, short len) {
// minimum command length // minimum command length
if (len < 12) return; if (len < sizeof(CmdPacket)) return;
// init pointers into buffer // init pointers into buffer
CmdPacket *packet = (CmdPacket*)buf; CmdPacket *packet = (CmdPacket*)buf;
uint8_t *data_ptr = (uint8_t*)&packet->args; uint8_t *data_ptr = (uint8_t*)&packet->args;
uint8_t *data_limit = data_ptr+len; uint8_t *data_limit = data_ptr+len;
DBG("CMD_parse_packet: cmd=%d(%s) argc=%d cb=%p ret=%lu\n", DBG("cmdParsePacket: cmd=%d argc=%d value=%lu\n",
packet->cmd, packet->cmd,
cmd_names[packet->cmd],
packet->argc, packet->argc,
(void *)packet->callback, packet->value
packet->_return
); );
#if 0 #if 0
@ -141,7 +119,7 @@ CMD_parse_packet(uint8_t *buf, short len) {
uint16_t argc = packet->argc; uint16_t argc = packet->argc;
while (data_ptr+2 < data_limit && argc--) { while (data_ptr+2 < data_limit && argc--) {
short l = *(uint16_t*)data_ptr; short l = *(uint16_t*)data_ptr;
os_printf("CMD_parse_packet: arg[%d] len=%d:", argn++, l); os_printf("cmdParsePacket: arg[%d] len=%d:", argn++, l);
data_ptr += 2; data_ptr += 2;
while (data_ptr < data_limit && l--) { while (data_ptr < data_limit && l--) {
os_printf(" %02X", *data_ptr++); os_printf(" %02X", *data_ptr++);
@ -151,9 +129,9 @@ CMD_parse_packet(uint8_t *buf, short len) {
#endif #endif
if (data_ptr <= data_limit) { if (data_ptr <= data_limit) {
CMD_Exec(commands, packet); cmdExec(commands, packet);
} else { } else {
DBG("CMD_parse_packet: packet length overrun, parsing arg %d\n", packet->argc); DBG("cmdParsePacket: packet length overrun, parsing arg %d\n", packet->argc);
} }
} }
@ -161,7 +139,7 @@ CMD_parse_packet(uint8_t *buf, short len) {
// Fill out a CmdRequest struct given a CmdPacket // Fill out a CmdRequest struct given a CmdPacket
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_Request(CmdRequest *req, CmdPacket* cmd) { cmdRequest(CmdRequest *req, CmdPacket* cmd) {
req->cmd = cmd; req->cmd = cmd;
req->arg_num = 0; req->arg_num = 0;
req->arg_ptr = (uint8_t*)&cmd->args; req->arg_ptr = (uint8_t*)&cmd->args;
@ -169,14 +147,14 @@ CMD_Request(CmdRequest *req, CmdPacket* cmd) {
// Return the number of arguments given a command struct // Return the number of arguments given a command struct
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
CMD_GetArgc(CmdRequest *req) { cmdGetArgc(CmdRequest *req) {
return req->cmd->argc; return req->cmd->argc;
} }
// Copy the next argument from a command structure into the data pointer, returns 0 on success // Copy the next argument from a command structure into the data pointer, returns 0 on success
// -1 on error // -1 on error
int32_t ICACHE_FLASH_ATTR int32_t ICACHE_FLASH_ATTR
CMD_PopArg(CmdRequest *req, void *data, uint16_t len) { cmdPopArg(CmdRequest *req, void *data, uint16_t len) {
uint16_t length; uint16_t length;
if (req->arg_num >= req->cmd->argc) if (req->arg_num >= req->cmd->argc)
@ -187,7 +165,7 @@ CMD_PopArg(CmdRequest *req, void *data, uint16_t len) {
req->arg_ptr += 2; req->arg_ptr += 2;
os_memcpy(data, req->arg_ptr, length); os_memcpy(data, req->arg_ptr, length);
req->arg_ptr += length; req->arg_ptr += (length+3)&~3; // round up to multiple of 4
req->arg_num ++; req->arg_num ++;
return 0; return 0;
@ -195,7 +173,7 @@ CMD_PopArg(CmdRequest *req, void *data, uint16_t len) {
// Skip the next argument // Skip the next argument
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_SkipArg(CmdRequest *req) { cmdSkipArg(CmdRequest *req) {
uint16_t length; uint16_t length;
if (req->arg_num >= req->cmd->argc) return; if (req->arg_num >= req->cmd->argc) return;
@ -203,12 +181,12 @@ CMD_SkipArg(CmdRequest *req) {
length = *(uint16_t*)req->arg_ptr; length = *(uint16_t*)req->arg_ptr;
req->arg_ptr += 2; req->arg_ptr += 2;
req->arg_ptr += length; req->arg_ptr += (length+3)&~3;
req->arg_num ++; req->arg_num ++;
} }
// Return the length of the next argument // Return the length of the next argument
uint16_t ICACHE_FLASH_ATTR uint16_t ICACHE_FLASH_ATTR
CMD_ArgLen(CmdRequest *req) { cmdArgLen(CmdRequest *req) {
return *(uint16_t*)req->arg_ptr; return *(uint16_t*)req->arg_ptr;
} }

@ -19,9 +19,8 @@ typedef struct __attribute__((__packed__)) {
typedef struct __attribute__((__packed__)) { typedef struct __attribute__((__packed__)) {
uint16_t cmd; // command to perform, from CmdName enum uint16_t cmd; // command to perform, from CmdName enum
uint32_t callback; // callback pointer to embed in response
uint32_t _return; // token to embed in response
uint16_t argc; // number of arguments to command uint16_t argc; // number of arguments to command
uint32_t value; // callback pointer for response or first argument
CmdArg args[0]; // really args[argc] CmdArg args[0]; // really args[argc]
} CmdPacket; } CmdPacket;
@ -34,65 +33,73 @@ typedef struct {
typedef enum { typedef enum {
CMD_NULL = 0, CMD_NULL = 0,
CMD_SYNC, // synchronize and clear CMD_SYNC, // synchronize and clear
CMD_IS_READY, // health-check CMD_RESP_V, // response with a value
CMD_WIFI_CONNECT, // (3) connect to AP (not honored in this implementation) CMD_RESP_CB, // response with a callback
CMD_MQTT_SETUP, CMD_WIFI_STATUS, // get the current wifi status
CMD_CB_ADD,
CMD_CB_EVENTS,
CMD_GET_TIME, // get current time in seconds since the unix epoch
CMD_MQTT_SETUP = 10,
CMD_MQTT_CONNECT, CMD_MQTT_CONNECT,
CMD_MQTT_DISCONNECT, CMD_MQTT_DISCONNECT,
CMD_MQTT_PUBLISH, CMD_MQTT_PUBLISH,
CMD_MQTT_SUBSCRIBE, CMD_MQTT_SUBSCRIBE,
CMD_MQTT_LWT, CMD_MQTT_LWT,
CMD_MQTT_EVENTS, CMD_MQTT_EVENTS,
CMD_REST_SETUP, // (11)
CMD_REST_SETUP = 20,
CMD_REST_REQUEST, CMD_REST_REQUEST,
CMD_REST_SETHEADER, CMD_REST_SETHEADER,
CMD_REST_EVENTS, CMD_REST_EVENTS,
CMD_CB_ADD, // 15
CMD_CB_EVENTS
} CmdName; } CmdName;
typedef uint32_t (*cmdfunc_t)(CmdPacket *cmd); typedef void (*cmdfunc_t)(CmdPacket *cmd);
typedef struct { typedef struct {
CmdName sc_name; CmdName sc_name; // name as CmdName enum
cmdfunc_t sc_function; char *sc_text; // name as string
cmdfunc_t sc_function; // pointer to function
} CmdList; } CmdList;
#define CMD_CBNLEN 16 #define CMD_CBNLEN 16
typedef struct { typedef struct {
char name[CMD_CBNLEN]; char name[CMD_CBNLEN];
uint32_t callback; uint32_t callback;
} cmdCallback; } CmdCallback;
// Used by slip protocol to cause parsing of a received packet // Used by slip protocol to cause parsing of a received packet
void CMD_parse_packet(uint8_t *buf, short len); void cmdParsePacket(uint8_t *buf, short len);
// Return the info about a callback to the attached uC by name, these are callbacks that the // Return the info about a callback to the attached uC by name, these are callbacks that the
// attached uC registers using the ADD_SENSOR command // attached uC registers using the ADD_SENSOR command
cmdCallback* CMD_GetCbByName(char* name); CmdCallback* cmdGetCbByName(char* name);
// Add a callback
uint32_t cmdAddCb(char *name, uint32_t callback);
// Responses // Responses
// Start a response, returns the partial CRC // Start a response
uint16_t CMD_ResponseStart(uint16_t cmd, uint32_t callback, uint32_t _return, uint16_t argc); void cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc);
// Adds data to a response, returns the partial CRC // Adds data to a response
uint16_t CMD_ResponseBody(uint16_t crc_in, uint8_t* data, short len); void cmdResponseBody(void* data, uint16_t len);
// Ends a response // Ends a response
void CMD_ResponseEnd(uint16_t crc); void cmdResponseEnd();
//void CMD_Response(uint16_t cmd, uint32_t callback, uint32_t _return, uint16_t argc, CmdArg* args[]); //void cmdResponse(uint16_t cmd, uint32_t callback, uint32_t value, uint16_t argc, CmdArg* args[]);
// Requests // Requests
// Fill out a CmdRequest struct given a CmdPacket // Fill out a CmdRequest struct given a CmdPacket
void CMD_Request(CmdRequest *req, CmdPacket* cmd); void cmdRequest(CmdRequest *req, CmdPacket* cmd);
// Return the number of arguments given a request // Return the number of arguments given a request
uint32_t CMD_GetArgc(CmdRequest *req); uint32_t cmdGetArgc(CmdRequest *req);
// Return the length of the next argument // Return the length of the next argument
uint16_t CMD_ArgLen(CmdRequest *req); uint16_t cmdArgLen(CmdRequest *req);
// Copy next arg from request into the data pointer, returns 0 on success, -1 on error // Copy next arg from request into the data pointer, returns 0 on success, -1 on error
int32_t CMD_PopArg(CmdRequest *req, void *data, uint16_t len); int32_t cmdPopArg(CmdRequest *req, void *data, uint16_t len);
// Skip next arg // Skip next arg
void CMD_SkipArg(CmdRequest *req); void cmdSkipArg(CmdRequest *req);
#endif #endif

@ -18,10 +18,10 @@
#define DBG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
static uint32_t CMD_Null(CmdPacket *cmd); static void cmdNull(CmdPacket *cmd);
//static uint32_t CMD_Reset(CmdPacket *cmd); static void cmdSync(CmdPacket *cmd);
static uint32_t CMD_WifiConnect(CmdPacket *cmd); static void cmdWifiStatus(CmdPacket *cmd);
static uint32_t CMD_AddCallback(CmdPacket *cmd); static void cmdAddCallback(CmdPacket *cmd);
// keep track of last status sent to uC so we can notify it when it changes // keep track of last status sent to uC so we can notify it when it changes
static uint8_t lastWifiStatus = wifiIsDisconnected; static uint8_t lastWifiStatus = wifiIsDisconnected;
@ -29,133 +29,145 @@ static bool wifiCbAdded = false;
// Command dispatch table for serial -> ESP commands // Command dispatch table for serial -> ESP commands
const CmdList commands[] = { const CmdList commands[] = {
{CMD_NULL, CMD_Null}, // no-op {CMD_NULL, "NULL", cmdNull}, // no-op
//{CMD_SYNC, CMD_Sync}, // synchronize {CMD_SYNC, "SYNC", cmdSync}, // synchronize
//{CMD_IS_READY, CMD_IsReady}, {CMD_WIFI_STATUS, "WIFI_STATUS", cmdWifiStatus},
{CMD_WIFI_CONNECT, CMD_WifiConnect}, {CMD_CB_ADD, "ADD_CB", cmdAddCallback},
#ifdef MQTT #ifdef MQTT
{CMD_MQTT_SETUP, MQTTCMD_Setup}, {CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup},
{CMD_MQTT_CONNECT, MQTTCMD_Connect}, {CMD_MQTT_CONNECT, "MQTT_CONN", MQTTCMD_Connect},
{CMD_MQTT_DISCONNECT, MQTTCMD_Disconnect}, {CMD_MQTT_DISCONNECT, "MQTT_DISCON", MQTTCMD_Disconnect},
{CMD_MQTT_PUBLISH, MQTTCMD_Publish}, {CMD_MQTT_PUBLISH, "MQTT_PUB", MQTTCMD_Publish},
{CMD_MQTT_SUBSCRIBE , MQTTCMD_Subscribe}, {CMD_MQTT_SUBSCRIBE , "MQTT_SUB", MQTTCMD_Subscribe},
{CMD_MQTT_LWT, MQTTCMD_Lwt}, {CMD_MQTT_LWT, "MQTT_LWT", MQTTCMD_Lwt},
#endif #endif
#ifdef REST #ifdef REST
{CMD_REST_SETUP, REST_Setup}, {CMD_REST_SETUP, "REST_SETUP", REST_Setup},
{CMD_REST_REQUEST, REST_Request}, {CMD_REST_REQUEST, "REST_REQ", REST_Request},
{CMD_REST_SETHEADER, REST_SetHeader}, {CMD_REST_SETHEADER, "REST_SETHDR", REST_SetHeader},
#endif #endif
{CMD_CB_ADD, CMD_AddCallback},
{CMD_NULL, NULL}
}; };
//===== List of registered callbacks (to uC)
// WifiCb plus 10 for sensors // WifiCb plus 10 for sensors
#define MAX_CALLBACKS 12 #define MAX_CALLBACKS 12
cmdCallback callbacks[MAX_CALLBACKS]; // cleared in CMD_Reset CmdCallback callbacks[MAX_CALLBACKS]; // cleared in cmdSync
// Command handler for Null command
static uint32_t ICACHE_FLASH_ATTR
CMD_Null(CmdPacket *cmd) {
return 1;
}
#if 0
// Command handler for Reset command, this was originally to reset the ESP but we don't want to
// do that in esp-link. It is still good to clear any information the ESP has about the attached
// uC.
static uint32_t ICACHE_FLASH_ATTR
CMD_Reset(CmdPacket *cmd) {
// clear callbacks table
os_memset(callbacks, 0, sizeof(callbacks));
return 1;
}
#endif
static uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
CMD_AddCb(char* name, uint32_t cb) { cmdAddCb(char* name, uint32_t cb) {
for (uint8_t i = 0; i < MAX_CALLBACKS; i++) { for (uint8_t i = 0; i < MAX_CALLBACKS; i++) {
//os_printf("CMD_AddCb: index %d name=%s cb=%p\n", i, callbacks[i].name, //os_printf("cmdAddCb: index %d name=%s cb=%p\n", i, callbacks[i].name,
// (void *)callbacks[i].callback); // (void *)callbacks[i].callback);
// find existing callback or add to the end // find existing callback or add to the end
if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0 || callbacks[i].name[0] == '\0') { if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0 || callbacks[i].name[0] == '\0') {
os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name)); os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name));
callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate
callbacks[i].callback = cb; callbacks[i].callback = cb;
DBG("CMD_AddCb: cb %s added at index %d\n", callbacks[i].name, i); DBG("cmdAddCb: '%s'->0x%lx added at %d\n", callbacks[i].name, cb, i);
return 1; return 1;
} }
} }
return 0; return 0;
} }
cmdCallback* ICACHE_FLASH_ATTR CmdCallback* ICACHE_FLASH_ATTR
CMD_GetCbByName(char* name) { cmdGetCbByName(char* name) {
for (uint8_t i = 0; i < MAX_CALLBACKS; i++) { for (uint8_t i = 0; i < MAX_CALLBACKS; i++) {
//os_printf("CMD_GetCbByName: index %d name=%s cb=%p\n", i, callbacks[i].name, //os_printf("cmdGetCbByName: index %d name=%s cb=%p\n", i, callbacks[i].name,
// (void *)callbacks[i].callback); // (void *)callbacks[i].callback);
// if callback doesn't exist or it's null // if callback doesn't exist or it's null
if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) { if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) {
DBG("CMD_GetCbByName: cb %s found at index %d\n", name, i); DBG("cmdGetCbByName: cb %s found at index %d\n", name, i);
return &callbacks[i]; return &callbacks[i];
} }
} }
os_printf("CMD_GetCbByName: cb %s not found\n", name); os_printf("cmdGetCbByName: cb %s not found\n", name);
return 0; return 0;
} }
//===== Wifi callback
// Callback from wifi subsystem to notify us of status changes // Callback from wifi subsystem to notify us of status changes
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_WifiCb(uint8_t wifiStatus) { cmdWifiCb(uint8_t wifiStatus) {
if (wifiStatus != lastWifiStatus){ if (wifiStatus != lastWifiStatus){
DBG("CMD_WifiCb: wifiStatus=%d\n", wifiStatus); DBG("cmdWifiCb: wifiStatus=%d\n", wifiStatus);
lastWifiStatus = wifiStatus; lastWifiStatus = wifiStatus;
cmdCallback *wifiCb = CMD_GetCbByName("wifiCb"); CmdCallback *wifiCb = cmdGetCbByName("wifiCb");
if ((uint32_t)wifiCb->callback != -1) { if ((uint32_t)wifiCb->callback != -1) {
uint8_t status = wifiStatus == wifiGotIP ? 5 : 1; uint8_t status = wifiStatus == wifiGotIP ? 5 : 1;
uint16_t crc = CMD_ResponseStart(CMD_WIFI_CONNECT, (uint32_t)wifiCb->callback, 0, 1); cmdResponseStart(CMD_RESP_CB, (uint32_t)wifiCb->callback, 1);
crc = CMD_ResponseBody(crc, (uint8_t*)&status, 1); cmdResponseBody((uint8_t*)&status, 1);
CMD_ResponseEnd(crc); cmdResponseEnd();
} }
} }
} }
// Command handler for Wifi connect command //===== Command handlers
static uint32_t ICACHE_FLASH_ATTR
CMD_WifiConnect(CmdPacket *cmd) { // Command handler for Null command
static void ICACHE_FLASH_ATTR
cmdNull(CmdPacket *cmd) {
}
// Command handler for sync command
static void ICACHE_FLASH_ATTR
cmdSync(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if(cmd->argc != 2 || cmd->callback == 0) if(cmd->argc != 0 || cmd->value == 0) {
return 0; cmdResponseStart(CMD_RESP_V, 0, 0);
cmdResponseEnd();
return;
}
// clear callbacks table
os_memset(callbacks, 0, sizeof(callbacks));
// register our callback with wifi subsystem
if (!wifiCbAdded) { if (!wifiCbAdded) {
wifiAddStateChangeCb(CMD_WifiCb); // register our callback with wifi subsystem wifiAddStateChangeCb(cmdWifiCb);
wifiCbAdded = true; wifiCbAdded = true;
} }
CMD_AddCb("wifiCb", (uint32_t)cmd->callback); // save the MCU's callback
// send OK response
cmdResponseStart(CMD_RESP_V, cmd->value, 0);
cmdResponseEnd();
// save the MCU's callback and trigger an initial callback
cmdAddCb("wifiCb", cmd->value);
lastWifiStatus = 0xff; // set to invalid value so we immediately send status cb in all cases lastWifiStatus = 0xff; // set to invalid value so we immediately send status cb in all cases
CMD_WifiCb(wifiState); cmdWifiCb(wifiState);
return;
}
return 1; // Command handler for wifi status command
static void ICACHE_FLASH_ATTR
cmdWifiStatus(CmdPacket *cmd) {
cmdResponseStart(CMD_RESP_V, wifiState, 0);
cmdResponseEnd();
return;
} }
// Command handler to add a callback to the named-callbacks list, this is for a callback to the uC // Command handler to add a callback to the named-callbacks list, this is for a callback to the uC
static uint32_t ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_AddCallback(CmdPacket *cmd) { cmdAddCallback(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if (cmd->argc != 1 || cmd->callback == 0) if (cmd->argc != 1 || cmd->value == 0) return;
return 0;
char name[16]; char name[16];
uint16_t len; uint16_t len;
// get the sensor name // get the callback name
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 15) return 0; // max size of name is 15 characters if (len > 15) return; // max size of name is 15 characters
if (CMD_PopArg(&req, (uint8_t *)name, len)) return 0; if (cmdPopArg(&req, (uint8_t *)name, len)) return;
name[len] = 0; name[len] = 0;
DBG("CMD_AddCallback: name=%s\n", name); DBG("cmdAddCallback: name=%s\n", name);
return CMD_AddCb(name, (uint32_t)cmd->callback); // save the sensor callback cmdAddCb(name, cmd->value); // save the sensor callback
} }

@ -30,8 +30,8 @@ cmdMqttConnectedCb(uint32_t* args) {
(void*)cb->disconnectedCb, (void*)cb->disconnectedCb,
(void*)cb->publishedCb, (void*)cb->publishedCb,
(void*)cb->dataCb); (void*)cb->dataCb);
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0); uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0);
CMD_ResponseEnd(crc); cmdResponseEnd(crc);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -39,8 +39,8 @@ cmdMqttDisconnectedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
DBG("MQTT: Disconnected\n"); DBG("MQTT: Disconnected\n");
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0); uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0);
CMD_ResponseEnd(crc); cmdResponseEnd(crc);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -48,8 +48,8 @@ cmdMqttPublishedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
DBG("MQTT: Published\n"); DBG("MQTT: Published\n");
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0); uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0);
CMD_ResponseEnd(crc); cmdResponseEnd(crc);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -58,23 +58,23 @@ cmdMqttDataCb(uint32_t* args, const char* topic, uint32_t topic_len, const char*
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->dataCb, 0, 2); crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->dataCb, 0, 2);
crc = CMD_ResponseBody(crc, (uint8_t*)topic, topic_len); crc = cmdResponseBody(crc, (uint8_t*)topic, topic_len);
crc = CMD_ResponseBody(crc, (uint8_t*)data, data_len); crc = cmdResponseBody(crc, (uint8_t*)data, data_len);
CMD_ResponseEnd(crc); cmdResponseEnd(crc);
} }
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Lwt(CmdPacket *cmd) { MQTTCMD_Lwt(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if (CMD_GetArgc(&req) != 5) if (cmdGetArgc(&req) != 5)
return 0; return 0;
// get mqtt client // get mqtt client
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); cmdPopArg(&req, (uint8_t*)&client_ptr, 4);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
@ -91,24 +91,24 @@ MQTTCMD_Lwt(CmdPacket *cmd) {
uint16_t len; uint16_t len;
// get topic // get topic
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) return 0; // safety check
client->connect_info.will_topic = (char*)os_zalloc(len + 1); client->connect_info.will_topic = (char*)os_zalloc(len + 1);
CMD_PopArg(&req, client->connect_info.will_topic, len); cmdPopArg(&req, client->connect_info.will_topic, len);
client->connect_info.will_topic[len] = 0; client->connect_info.will_topic[len] = 0;
// get message // get message
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) return 0; // safety check
client->connect_info.will_message = (char*)os_zalloc(len + 1); client->connect_info.will_message = (char*)os_zalloc(len + 1);
CMD_PopArg(&req, client->connect_info.will_message, len); cmdPopArg(&req, client->connect_info.will_message, len);
client->connect_info.will_message[len] = 0; client->connect_info.will_message[len] = 0;
// get qos // get qos
CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_qos, 4); cmdPopArg(&req, (uint8_t*)&client->connect_info.will_qos, 4);
// get retain // get retain
CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4); cmdPopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4);
DBG("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n", DBG("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n",
client->connect_info.will_topic, client->connect_info.will_topic,
@ -124,14 +124,14 @@ MQTTCMD_Lwt(CmdPacket *cmd) {
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Publish(CmdPacket *cmd) { MQTTCMD_Publish(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if (CMD_GetArgc(&req) != 6) if (cmdGetArgc(&req) != 6)
return 0; return 0;
// get mqtt client // get mqtt client
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); cmdPopArg(&req, (uint8_t*)&client_ptr, 4);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
@ -142,33 +142,33 @@ MQTTCMD_Publish(CmdPacket *cmd) {
uint16_t len; uint16_t len;
// get topic // get topic
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) return 0; // safety check
uint8_t *topic = (uint8_t*)os_zalloc(len + 1); uint8_t *topic = (uint8_t*)os_zalloc(len + 1);
CMD_PopArg(&req, topic, len); cmdPopArg(&req, topic, len);
topic[len] = 0; topic[len] = 0;
// get data // get data
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
uint8_t *data = (uint8_t*)os_zalloc(len+1); uint8_t *data = (uint8_t*)os_zalloc(len+1);
if (!data) { // safety check if (!data) { // safety check
os_free(topic); os_free(topic);
return 0; return 0;
} }
CMD_PopArg(&req, data, len); cmdPopArg(&req, data, len);
data[len] = 0; data[len] = 0;
uint32_t qos, retain, data_len; uint32_t qos, retain, data_len;
// get data length // get data length
// this isn't used but we have to pull it off the stack // this isn't used but we have to pull it off the stack
CMD_PopArg(&req, (uint8_t*)&data_len, 4); cmdPopArg(&req, (uint8_t*)&data_len, 4);
// get qos // get qos
CMD_PopArg(&req, (uint8_t*)&qos, 4); cmdPopArg(&req, (uint8_t*)&qos, 4);
// get retain // get retain
CMD_PopArg(&req, (uint8_t*)&retain, 4); cmdPopArg(&req, (uint8_t*)&retain, 4);
DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n", DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n",
topic, topic,
@ -185,14 +185,14 @@ MQTTCMD_Publish(CmdPacket *cmd) {
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Subscribe(CmdPacket *cmd) { MQTTCMD_Subscribe(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if (CMD_GetArgc(&req) != 3) if (cmdGetArgc(&req) != 3)
return 0; return 0;
// get mqtt client // get mqtt client
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); cmdPopArg(&req, (uint8_t*)&client_ptr, 4);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
@ -203,15 +203,15 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
uint16_t len; uint16_t len;
// get topic // get topic
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) return 0; // safety check
uint8_t* topic = (uint8_t*)os_zalloc(len + 1); uint8_t* topic = (uint8_t*)os_zalloc(len + 1);
CMD_PopArg(&req, topic, len); cmdPopArg(&req, topic, len);
topic[len] = 0; topic[len] = 0;
// get qos // get qos
uint32_t qos = 0; uint32_t qos = 0;
CMD_PopArg(&req, (uint8_t*)&qos, 4); cmdPopArg(&req, (uint8_t*)&qos, 4);
DBG("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos); DBG("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos);
@ -223,17 +223,17 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Setup(CmdPacket *cmd) { MQTTCMD_Setup(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
CMD_SkipArg(&req); cmdSkipArg(&req);
CMD_SkipArg(&req); cmdSkipArg(&req);
CMD_SkipArg(&req); cmdSkipArg(&req);
CMD_SkipArg(&req); cmdSkipArg(&req);
CMD_SkipArg(&req); cmdSkipArg(&req);
#else #else
if (CMD_GetArgc(&req) != 9) if (cmdGetArgc(&req) != 9)
return 0; return 0;
// create mqtt client // create mqtt client
@ -247,31 +247,31 @@ MQTTCMD_Setup(CmdPacket *cmd) {
uint32_t keepalive, clean_session; uint32_t keepalive, clean_session;
// get client id // get client id
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 32) return 0; // safety check if (len > 32) return 0; // safety check
client_id = (uint8_t*)os_zalloc(len + 1); client_id = (uint8_t*)os_zalloc(len + 1);
CMD_PopArg(&req, client_id, len); cmdPopArg(&req, client_id, len);
client_id[len] = 0; client_id[len] = 0;
// get username // get username
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 32) return 0; // safety check if (len > 32) return 0; // safety check
user_data = (uint8_t*)os_zalloc(len + 1); user_data = (uint8_t*)os_zalloc(len + 1);
CMD_PopArg(&req, user_data, len); cmdPopArg(&req, user_data, len);
user_data[len] = 0; user_data[len] = 0;
// get password // get password
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 32) return 0; // safety check if (len > 32) return 0; // safety check
pass_data = (uint8_t*)os_zalloc(len + 1); pass_data = (uint8_t*)os_zalloc(len + 1);
CMD_PopArg(&req, pass_data, len); cmdPopArg(&req, pass_data, len);
pass_data[len] = 0; pass_data[len] = 0;
// get keepalive // get keepalive
CMD_PopArg(&req, (uint8_t*)&keepalive, 4); cmdPopArg(&req, (uint8_t*)&keepalive, 4);
// get clean session // get clean session
CMD_PopArg(&req, (uint8_t*)&clean_session, 4); cmdPopArg(&req, (uint8_t*)&clean_session, 4);
#ifdef MQTTCMD_DBG #ifdef MQTTCMD_DBG
DBG("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session); DBG("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session);
#endif #endif
@ -289,13 +289,13 @@ MQTTCMD_Setup(CmdPacket *cmd) {
MqttCmdCb* callback = (MqttCmdCb*)os_zalloc(sizeof(MqttCmdCb)); MqttCmdCb* callback = (MqttCmdCb*)os_zalloc(sizeof(MqttCmdCb));
uint32_t cb_data; uint32_t cb_data;
CMD_PopArg(&req, (uint8_t*)&cb_data, 4); cmdPopArg(&req, (uint8_t*)&cb_data, 4);
callback->connectedCb = cb_data; callback->connectedCb = cb_data;
CMD_PopArg(&req, (uint8_t*)&cb_data, 4); cmdPopArg(&req, (uint8_t*)&cb_data, 4);
callback->disconnectedCb = cb_data; callback->disconnectedCb = cb_data;
CMD_PopArg(&req, (uint8_t*)&cb_data, 4); cmdPopArg(&req, (uint8_t*)&cb_data, 4);
callback->publishedCb = cb_data; callback->publishedCb = cb_data;
CMD_PopArg(&req, (uint8_t*)&cb_data, 4); cmdPopArg(&req, (uint8_t*)&cb_data, 4);
callback->dataCb = cb_data; callback->dataCb = cb_data;
client->user_data = callback; client->user_data = callback;
@ -311,7 +311,7 @@ MQTTCMD_Setup(CmdPacket *cmd) {
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Connect(CmdPacket *cmd) { MQTTCMD_Connect(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
@ -325,12 +325,12 @@ MQTTCMD_Connect(CmdPacket *cmd) {
return 1; return 1;
#else #else
if (CMD_GetArgc(&req) != 4) if (cmdGetArgc(&req) != 4)
return 0; return 0;
// get mqtt client // get mqtt client
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); cmdPopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr);
@ -339,17 +339,17 @@ MQTTCMD_Connect(CmdPacket *cmd) {
// get host // get host
if (client->host) if (client->host)
os_free(client->host); os_free(client->host);
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) return 0; // safety check
client->host = (char*)os_zalloc(len + 1); client->host = (char*)os_zalloc(len + 1);
CMD_PopArg(&req, client->host, len); cmdPopArg(&req, client->host, len);
client->host[len] = 0; client->host[len] = 0;
// get port // get port
CMD_PopArg(&req, (uint8_t*)&client->port, 4); cmdPopArg(&req, (uint8_t*)&client->port, 4);
// get security // get security
CMD_PopArg(&req, (uint8_t*)&client->security, 4); cmdPopArg(&req, (uint8_t*)&client->security, 4);
DBG("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n", DBG("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n",
client->host, client->host,
client->port, client->port,
@ -363,18 +363,18 @@ MQTTCMD_Connect(CmdPacket *cmd) {
uint32_t ICACHE_FLASH_ATTR uint32_t ICACHE_FLASH_ATTR
MQTTCMD_Disconnect(CmdPacket *cmd) { MQTTCMD_Disconnect(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
return 1; return 1;
#else #else
if (CMD_GetArgc(&req) != 1) if (cmdGetArgc(&req) != 1)
return 0; return 0;
// get mqtt client // get mqtt client
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); cmdPopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr);

@ -10,11 +10,11 @@ typedef struct {
uint32_t dataCb; uint32_t dataCb;
} MqttCmdCb; } MqttCmdCb;
uint32_t MQTTCMD_Connect(CmdPacket *cmd); void MQTTCMD_Connect(CmdPacket *cmd);
uint32_t MQTTCMD_Disconnect(CmdPacket *cmd); void MQTTCMD_Disconnect(CmdPacket *cmd);
uint32_t MQTTCMD_Setup(CmdPacket *cmd); void MQTTCMD_Setup(CmdPacket *cmd);
uint32_t MQTTCMD_Publish(CmdPacket *cmd); void MQTTCMD_Publish(CmdPacket *cmd);
uint32_t MQTTCMD_Subscribe(CmdPacket *cmd); void MQTTCMD_Subscribe(CmdPacket *cmd);
uint32_t MQTTCMD_Lwt(CmdPacket *cmd); void MQTTCMD_Lwt(CmdPacket *cmd);
#endif /* MODULES_MQTT_CMD_H_ */ #endif /* MODULES_MQTT_CMD_H_ */

@ -3,6 +3,8 @@
// Adapted from: github.com/tuanpmt/esp_bridge, Created on: Mar 4, 2015, Author: Minh // Adapted from: github.com/tuanpmt/esp_bridge, Created on: Mar 4, 2015, Author: Minh
#include "esp8266.h" #include "esp8266.h"
#include "c_types.h"
#include "ip_addr.h"
#include "rest.h" #include "rest.h"
#include "cmd.h" #include "cmd.h"
@ -12,6 +14,27 @@
#define DBG_REST(format, ...) do { } while(0) #define DBG_REST(format, ...) do { } while(0)
#endif #endif
typedef enum {
HEADER_GENERIC = 0,
HEADER_CONTENT_TYPE,
HEADER_USER_AGENT
} HEADER_TYPE;
typedef struct {
char *host;
uint32_t port;
uint32_t security;
ip_addr_t ip;
struct espconn *pCon;
char *header;
char *data;
uint16_t data_len;
uint16_t data_sent;
char *content_type;
char *user_agent;
uint32_t resp_cb;
} RestClient;
// Connection pool for REST clients. Attached MCU's just call REST_setup and this allocates // Connection pool for REST clients. Attached MCU's just call REST_setup and this allocates
// a connection, They never call any 'free' and given that the attached MCU could restart at // a connection, They never call any 'free' and given that the attached MCU could restart at
@ -32,7 +55,7 @@ tcpclient_recv(void *arg, char *pdata, unsigned short len) {
// parse status line // parse status line
int pi = 0; int pi = 0;
int32_t code = -1; int16_t code = -1;
char statusCode[4] = "\0\0\0\0"; char statusCode[4] = "\0\0\0\0";
int statusLen = 0; int statusLen = 0;
bool inStatus = false; bool inStatus = false;
@ -69,15 +92,17 @@ tcpclient_recv(void *arg, char *pdata, unsigned short len) {
//if (pi < len && pdata[pi] == '\r') pi++; // hacky! //if (pi < len && pdata[pi] == '\r') pi++; // hacky!
// collect body and send it // collect body and send it
uint16_t crc;
int body_len = len-pi; int body_len = len-pi;
DBG_REST("REST: status=%ld, body=%d\n", code, body_len); DBG_REST("REST: status=%d, body=%d\n", code, body_len);
if (pi == len) { if (pi == len) {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 0); cmdResponseStart(CMD_RESP_CB, client->resp_cb, 1);
cmdResponseBody(&code, sizeof(code));
cmdResponseEnd();
} else { } else {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 1); cmdResponseStart(CMD_RESP_CB, client->resp_cb, 2);
crc = CMD_ResponseBody(crc, (uint8_t*)(pdata+pi), body_len); cmdResponseBody(&code, sizeof(code));
CMD_ResponseEnd(crc); cmdResponseBody(pdata+pi, body_len>100?100:body_len);
cmdResponseEnd();
#if 0 #if 0
os_printf("REST: body="); os_printf("REST: body=");
for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]); for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]);
@ -89,7 +114,6 @@ tcpclient_recv(void *arg, char *pdata, unsigned short len) {
// espconn_secure_disconnect(client->pCon); // espconn_secure_disconnect(client->pCon);
//else //else
espconn_disconnect(client->pCon); espconn_disconnect(client->pCon);
} }
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
@ -173,33 +197,39 @@ rest_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
} }
} }
uint32_t ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
REST_Setup(CmdPacket *cmd) { REST_Setup(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
uint32_t port, security; uint32_t port, security;
int32_t err = -1; // error code in case of failure
// start parsing the command // start parsing the command
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if(CMD_GetArgc(&req) != 3) return 0; if(cmdGetArgc(&req) != 3) goto fail;
err--;
// get the hostname // get the hostname
uint16_t len = CMD_ArgLen(&req); uint16_t len = cmdArgLen(&req);
if (len > 128) return 0; // safety check if (len > 128) goto fail; // safety check
err--;
uint8_t *rest_host = (uint8_t*)os_zalloc(len + 1); uint8_t *rest_host = (uint8_t*)os_zalloc(len + 1);
if (CMD_PopArg(&req, rest_host, len)) return 0; if (cmdPopArg(&req, rest_host, len)) goto fail;
err--;
rest_host[len] = 0; rest_host[len] = 0;
// get the port // get the port
if (CMD_PopArg(&req, (uint8_t*)&port, 4)) { if (cmdPopArg(&req, (uint8_t*)&port, 2)) {
os_free(rest_host); os_free(rest_host);
return 0; goto fail;
} }
err--;
// get the security mode // get the security mode
if (CMD_PopArg(&req, (uint8_t*)&security, 4)) { if (cmdPopArg(&req, (uint8_t*)&security, 1)) {
os_free(rest_host); os_free(rest_host);
return 0; goto fail;
} }
err--;
// clear connection structures the first time // clear connection structures the first time
if (restNum == 0xff) { if (restNum == 0xff) {
@ -224,7 +254,7 @@ REST_Setup(CmdPacket *cmd) {
os_memset(client, 0, sizeof(RestClient)); os_memset(client, 0, sizeof(RestClient));
DBG_REST("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security); DBG_REST("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security);
client->resp_cb = cmd->callback; client->resp_cb = cmd->value;
client->host = (char *)rest_host; client->host = (char *)rest_host;
client->port = port; client->port = port;
@ -249,35 +279,39 @@ REST_Setup(CmdPacket *cmd) {
client->pCon->reverse = client; client->pCon->reverse = client;
return REST_CB | (uint32_t)clientNum; cmdResponseStart(CMD_RESP_V, clientNum, 0);
cmdResponseEnd();
return;
fail:
cmdResponseStart(CMD_RESP_V, err, 0);
cmdResponseEnd();
return;
} }
uint32_t ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
REST_SetHeader(CmdPacket *cmd) { REST_SetHeader(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
if(CMD_GetArgc(&req) != 3) if(cmdGetArgc(&req) != 2) return;
return 0;
// Get client // Get client
uint32_t clientNum; uint32_t clientNum = cmd->value;
if (CMD_PopArg(&req, (uint8_t*)&clientNum, 4)) return 0; RestClient *client = restClient + (clientNum % MAX_REST);
if ((clientNum & 0xffff0000) != REST_CB) return 0;
RestClient *client = restClient + ((clientNum & 0xffff) % MAX_REST);
// Get header selector // Get header selector
uint32_t header_index; uint32_t header_index;
if (CMD_PopArg(&req, (uint8_t*)&header_index, 4)) return 0; if (cmdPopArg(&req, (uint8_t*)&header_index, 4)) return;
// Get header value // Get header value
uint16_t len = CMD_ArgLen(&req); uint16_t len = cmdArgLen(&req);
if (len > 256) return 0; //safety check if (len > 256) return; //safety check
switch(header_index) { switch(header_index) {
case HEADER_GENERIC: case HEADER_GENERIC:
if(client->header) os_free(client->header); if(client->header) os_free(client->header);
client->header = (char*)os_zalloc(len + 3); client->header = (char*)os_zalloc(len + 3);
CMD_PopArg(&req, (uint8_t*)client->header, len); cmdPopArg(&req, (uint8_t*)client->header, len);
client->header[len] = '\r'; client->header[len] = '\r';
client->header[len+1] = '\n'; client->header[len+1] = '\n';
client->header[len+2] = 0; client->header[len+2] = 0;
@ -286,7 +320,7 @@ REST_SetHeader(CmdPacket *cmd) {
case HEADER_CONTENT_TYPE: case HEADER_CONTENT_TYPE:
if(client->content_type) os_free(client->content_type); if(client->content_type) os_free(client->content_type);
client->content_type = (char*)os_zalloc(len + 3); client->content_type = (char*)os_zalloc(len + 3);
CMD_PopArg(&req, (uint8_t*)client->content_type, len); cmdPopArg(&req, (uint8_t*)client->content_type, len);
client->content_type[len] = '\r'; client->content_type[len] = '\r';
client->content_type[len+1] = '\n'; client->content_type[len+1] = '\n';
client->content_type[len+2] = 0; client->content_type[len+2] = 0;
@ -295,52 +329,50 @@ REST_SetHeader(CmdPacket *cmd) {
case HEADER_USER_AGENT: case HEADER_USER_AGENT:
if(client->user_agent) os_free(client->user_agent); if(client->user_agent) os_free(client->user_agent);
client->user_agent = (char*)os_zalloc(len + 3); client->user_agent = (char*)os_zalloc(len + 3);
CMD_PopArg(&req, (uint8_t*)client->user_agent, len); cmdPopArg(&req, (uint8_t*)client->user_agent, len);
client->user_agent[len] = '\r'; client->user_agent[len] = '\r';
client->user_agent[len+1] = '\n'; client->user_agent[len+1] = '\n';
client->user_agent[len+2] = 0; client->user_agent[len+2] = 0;
DBG_REST("REST: Set user_agent: %s\r\n", client->user_agent); DBG_REST("REST: Set user_agent: %s\r\n", client->user_agent);
break; break;
} }
return 1;
} }
uint32_t ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
REST_Request(CmdPacket *cmd) { REST_Request(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); cmdRequest(&req, cmd);
DBG_REST("REST: request"); DBG_REST("REST: request");
if (cmd->argc != 2 && cmd->argc != 3) return;
// Get client // Get client
uint32_t clientNum; uint32_t clientNum = cmd->value;
if (CMD_PopArg(&req, (uint8_t*)&clientNum, 4)) goto fail; RestClient *client = restClient + (clientNum % MAX_REST);
if ((clientNum & 0xffff0000) != REST_CB) goto fail;
clientNum &= 0xffff;
RestClient *client = restClient + clientNum % MAX_REST;
DBG_REST(" #%ld", clientNum); DBG_REST(" #%ld", clientNum);
// Get HTTP method // Get HTTP method
uint16_t len = CMD_ArgLen(&req); uint16_t len = cmdArgLen(&req);
if (len > 15) goto fail; if (len > 15) goto fail;
char method[16]; char method[16];
CMD_PopArg(&req, method, len); cmdPopArg(&req, method, len);
method[len] = 0; method[len] = 0;
DBG_REST(" method=%s", method); DBG_REST(" method=%s", method);
// Get HTTP path // Get HTTP path
len = CMD_ArgLen(&req); len = cmdArgLen(&req);
if (len > 1023) goto fail; if (len > 1023) goto fail;
char path[1024]; char path[1024];
CMD_PopArg(&req, path, len); cmdPopArg(&req, path, len);
path[len] = 0; path[len] = 0;
DBG_REST(" path=%s", path); DBG_REST(" path=%s", path);
// Get HTTP body // Get HTTP body
uint32_t realLen = 0; uint32_t realLen = 0;
if (CMD_GetArgc(&req) == 3) { if (cmdGetArgc(&req) == 2) {
realLen = 0; realLen = 0;
len = 0;
} else { } else {
CMD_PopArg(&req, (uint8_t*)&realLen, 4); realLen = cmdArgLen(&req);
if (realLen > 2048) goto fail;
len = CMD_ArgLen(&req);
if (len > 2048 || realLen > len) goto fail;
} }
DBG_REST(" bodyLen=%ld", realLen); DBG_REST(" bodyLen=%ld", realLen);
@ -367,14 +399,14 @@ REST_Request(CmdPacket *cmd) {
DBG_REST(" hdrLen=%d", client->data_len); DBG_REST(" hdrLen=%d", client->data_len);
if (realLen > 0) { if (realLen > 0) {
CMD_PopArg(&req, client->data + client->data_len, realLen); cmdPopArg(&req, client->data + client->data_len, realLen);
client->data_len += realLen; client->data_len += realLen;
} }
DBG_REST("\n"); DBG_REST("\n");
//DBG_REST("REST request: %s", (char*)client->data); //DBG_REST("REST request: %s", (char*)client->data);
DBG_REST("REST: pCon state=%d\n", client->pCon->state); //DBG_REST("REST: pCon state=%d\n", client->pCon->state);
client->pCon->state = ESPCONN_NONE; client->pCon->state = ESPCONN_NONE;
espconn_regist_connectcb(client->pCon, tcpclient_connect_cb); espconn_regist_connectcb(client->pCon, tcpclient_connect_cb);
espconn_regist_reconcb(client->pCon, tcpclient_recon_cb); espconn_regist_reconcb(client->pCon, tcpclient_recon_cb);
@ -392,9 +424,8 @@ REST_Request(CmdPacket *cmd) {
espconn_gethostbyname(client->pCon, (char *)client->host, &client->ip, rest_dns_found); espconn_gethostbyname(client->pCon, (char *)client->host, &client->ip, rest_dns_found);
} }
return 1; return;
fail: fail:
DBG_REST("\n"); DBG_REST("\n");
return 0;
} }

@ -8,33 +8,10 @@
#ifndef MODULES_API_H_ #ifndef MODULES_API_H_
#define MODULES_API_H_ #define MODULES_API_H_
#include "c_types.h"
#include "ip_addr.h"
#include "cmd.h" #include "cmd.h"
typedef enum { void REST_Setup(CmdPacket *cmd);
HEADER_GENERIC = 0, void REST_Request(CmdPacket *cmd);
HEADER_CONTENT_TYPE, void REST_SetHeader(CmdPacket *cmd);
HEADER_USER_AGENT
} HEADER_TYPE;
typedef struct {
char *host;
uint32_t port;
uint32_t security;
ip_addr_t ip;
struct espconn *pCon;
char *header;
char *data;
uint16_t data_len;
uint16_t data_sent;
char *content_type;
char *user_agent;
uint32_t resp_cb;
} RestClient;
uint32_t REST_Setup(CmdPacket *cmd);
uint32_t REST_Request(CmdPacket *cmd);
uint32_t REST_SetHeader(CmdPacket *cmd);
#endif /* MODULES_INCLUDE_API_H_ */ #endif /* MODULES_INCLUDE_API_H_ */

@ -43,7 +43,7 @@ slip_process() {
uint16_t crc = crc16_data((uint8_t*)slip_buf, slip_len-2, 0); uint16_t crc = crc16_data((uint8_t*)slip_buf, slip_len-2, 0);
uint16_t rcv = ((uint16_t)slip_buf[slip_len-2]) | ((uint16_t)slip_buf[slip_len-1] << 8); uint16_t rcv = ((uint16_t)slip_buf[slip_len-2]) | ((uint16_t)slip_buf[slip_len-1] << 8);
if (crc == rcv) { if (crc == rcv) {
CMD_parse_packet((uint8_t*)slip_buf, slip_len-2); cmdParsePacket((uint8_t*)slip_buf, slip_len-2);
} else { } else {
os_printf("SLIP: bad CRC, crc=%04x rcv=%04x len=%d\n", crc, rcv, slip_len); os_printf("SLIP: bad CRC, crc=%04x rcv=%04x len=%d\n", crc, rcv, slip_len);

Loading…
Cancel
Save