diff --git a/README.md b/README.md index 44e97f3..f817ae9 100644 --- a/README.md +++ b/README.md @@ -235,18 +235,29 @@ Troubleshooting Building the firmware --------------------- The firmware has been built using the [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk) -on a Linux system. Create an esp8266 directory, install the esp-open-sdk into a sub-directory. +on a Linux system. Create an esp8266 directory, install the esp-open-sdk into a sub-directory +using the *non-standalone* install (i.e., there should not be an sdk directory in the esp-open-sdk +dir when done installing, if you use the standalone install you will get compilation errors +with std types, such as `uint32_t`). + Download the Espressif SDK (use the version mentioned in the release notes) from their [download forum](http://bbs.espressif.com/viewforum.php?f=5) and also expand it into a -sub-directory. Then clone the esp-link repository into a third sub-directory. +sub-directory. + +Clone the esp-link repository into a third sub-directory and check out the tag you would like, +such as `git checkout v2.1.7`. This way the relative paths in the Makefile will work. If you choose a different directory structure look at the Makefile for the appropriate environment variables to define. +Do not use the source tarballs from the release page on github, +these will give you trouble compiling because the Makefile uses git to determine the esp-link +version being built. In order to OTA-update the esp8266 you should `export ESP_HOSTNAME=...` with the hostname or IP address of your module. -Now, build the code: `make` in the top-level of esp-link. +Now, build the code: `make` in the top-level of esp-link. If you want to se the commands being +issued, use `VERBOSE=1 make`. A few notes from others (I can't fully verify these): - You may need to install `zlib1g-dev` and `python-serial` diff --git a/cmd/cmd.c b/cmd/cmd.c index 52ee3b3..714d185 100644 --- a/cmd/cmd.c +++ b/cmd/cmd.c @@ -34,7 +34,7 @@ cmdProtoWrite(uint8_t data) { } static void ICACHE_FLASH_ATTR -cmdProtoWriteBuf(uint8_t *data, short len) { +cmdProtoWriteBuf(const uint8_t *data, short len) { while (len--) cmdProtoWrite(*data++); } @@ -56,7 +56,7 @@ cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc) { // Adds data to a response, returns the partial CRC void ICACHE_FLASH_ATTR -cmdResponseBody(void *data, uint16_t len) { +cmdResponseBody(const void *data, uint16_t len) { cmdProtoWriteBuf((uint8_t*)&len, 2); resp_crc = crc16_data((uint8_t*)&len, 2, resp_crc); diff --git a/cmd/cmd.h b/cmd/cmd.h index 42e6fe0..6b4b018 100644 --- a/cmd/cmd.h +++ b/cmd/cmd.h @@ -40,18 +40,14 @@ typedef enum { CMD_CB_EVENTS, CMD_GET_TIME, // get current time in seconds since the unix epoch - CMD_MQTT_SETUP = 10, - CMD_MQTT_CONNECT, - CMD_MQTT_DISCONNECT, - CMD_MQTT_PUBLISH, - CMD_MQTT_SUBSCRIBE, - CMD_MQTT_LWT, - CMD_MQTT_EVENTS, + CMD_MQTT_SETUP = 10, // set-up callbacks + CMD_MQTT_PUBLISH, // publish a message + CMD_MQTT_SUBSCRIBE, // subscribe to a topic + CMD_MQTT_LWT, // set the last-will-topic and messge CMD_REST_SETUP = 20, CMD_REST_REQUEST, CMD_REST_SETHEADER, - CMD_REST_EVENTS, } CmdName; typedef void (*cmdfunc_t)(CmdPacket *cmd); @@ -83,7 +79,7 @@ uint32_t cmdAddCb(char *name, uint32_t callback); // Start a response void cmdResponseStart(uint16_t cmd, uint32_t value, uint16_t argc); // Adds data to a response -void cmdResponseBody(void* data, uint16_t len); +void cmdResponseBody(const void* data, uint16_t len); // Ends a response void cmdResponseEnd(); diff --git a/cmd/handlers.c b/cmd/handlers.c index cb4aa21..2b9c1ad 100644 --- a/cmd/handlers.c +++ b/cmd/handlers.c @@ -35,8 +35,6 @@ const CmdList commands[] = { {CMD_CB_ADD, "ADD_CB", cmdAddCallback}, #ifdef MQTT {CMD_MQTT_SETUP, "MQTT_SETUP", MQTTCMD_Setup}, - {CMD_MQTT_CONNECT, "MQTT_CONN", MQTTCMD_Connect}, - {CMD_MQTT_DISCONNECT, "MQTT_DISCON", MQTTCMD_Disconnect}, {CMD_MQTT_PUBLISH, "MQTT_PUB", MQTTCMD_Publish}, {CMD_MQTT_SUBSCRIBE , "MQTT_SUB", MQTTCMD_Subscribe}, {CMD_MQTT_LWT, "MQTT_LWT", MQTTCMD_Lwt}, diff --git a/esp-link/mqtt_client.c b/esp-link/mqtt_client.c index 12b9a8d..f0d9108 100644 --- a/esp-link/mqtt_client.c +++ b/esp-link/mqtt_client.c @@ -18,34 +18,31 @@ static MqttCallback published_cb; static MqttDataCallback data_cb; void ICACHE_FLASH_ATTR -mqttConnectedCb(uint32_t *args) { +mqttConnectedCb(MQTT_Client* client) { DBG("MQTT Client: Connected\n"); - //MQTT_Client* client = (MQTT_Client*)args; //MQTT_Subscribe(client, "system/time", 0); // handy for testing if (connected_cb) - connected_cb(args); + connected_cb(client); } void ICACHE_FLASH_ATTR -mqttDisconnectedCb(uint32_t *args) { -// MQTT_Client* client = (MQTT_Client*)args; +mqttDisconnectedCb(MQTT_Client* client) { DBG("MQTT Client: Disconnected\n"); if (disconnected_cb) - disconnected_cb(args); + disconnected_cb(client); } void ICACHE_FLASH_ATTR -mqttPublishedCb(uint32_t *args) { -// MQTT_Client* client = (MQTT_Client*)args; +mqttPublishedCb(MQTT_Client* client) { DBG("MQTT Client: Published\n"); if (published_cb) - published_cb(args); + published_cb(client); } void ICACHE_FLASH_ATTR -mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) { - // MQTT_Client* client = (MQTT_Client*)args; - +mqttDataCb(MQTT_Client* client, const char* topic, uint32_t topic_len, + const char *data, uint32_t data_len) +{ #ifdef MQTTCLIENT_DBG char *topicBuf = (char*)os_zalloc(topic_len + 1); char *dataBuf = (char*)os_zalloc(data_len + 1); @@ -62,7 +59,7 @@ mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *da #endif if (data_cb) - data_cb(args, topic, topic_len, data, data_len); + data_cb(client, topic, topic_len, data, data_len); } void ICACHE_FLASH_ATTR diff --git a/esp-link/status.c b/esp-link/status.c index a49726f..6905850 100644 --- a/esp-link/status.c +++ b/esp-link/status.c @@ -37,7 +37,7 @@ static void ICACHE_FLASH_ATTR mqttStatusCb(void *v) { char buf[128]; mqttStatusMsg(buf); - MQTT_Publish(&mqttClient, flashConfig.mqtt_status_topic, buf, 1, 0); + MQTT_Publish(&mqttClient, flashConfig.mqtt_status_topic, buf, os_strlen(buf), 1, 0); } diff --git a/mqtt/mqtt.c b/mqtt/mqtt.c index d3d174e..30e2dd0 100644 --- a/mqtt/mqtt.c +++ b/mqtt/mqtt.c @@ -89,9 +89,9 @@ deliver_publish(MQTT_Client* client, uint8_t* message, uint16_t length) { // callback to client if (client->dataCb) - client->dataCb((uint32_t*)client, topic, topic_length, data, data_length); + client->dataCb(client, topic, topic_length, data, data_length); if (client->cmdDataCb) - client->cmdDataCb((uint32_t*)client, topic, topic_length, data, data_length); + client->cmdDataCb(client, topic, topic_length, data, data_length); } /** @@ -164,8 +164,8 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) { case MQTT_MSG_TYPE_CONNACK: //DBG_MQTT("MQTT: Connect successful\n"); // callbacks for internal and external clients - if (client->connectedCb) client->connectedCb((uint32_t*)client); - if (client->cmdConnectedCb) client->cmdConnectedCb((uint32_t*)client); + if (client->connectedCb) client->connectedCb(client); + if (client->cmdConnectedCb) client->cmdConnectedCb(client); client->reconTimeout = 1; // reset the reconnect backoff break; @@ -357,8 +357,8 @@ mqtt_tcpclient_discon_cb(void* arg) { // if this is an aborted connection we're done if (client == NULL) return; DBG_MQTT("MQTT: Disconnected from %s:%d\n", client->host, client->port); - if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client); - if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client); + if (client->disconnectedCb) client->disconnectedCb(client); + if (client->cmdDisconnectedCb) client->cmdDisconnectedCb(client); // reconnect unless we're in a permanently disconnected state if (client->connState == MQTT_DISCONNECTED) return; @@ -380,8 +380,8 @@ mqtt_tcpclient_recon_cb(void* arg, int8_t err) { if (pespconn->proto.tcp) os_free(pespconn->proto.tcp); os_free(pespconn); os_printf("MQTT: Connection reset from %s:%d\n", client->host, client->port); - if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client); - if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client); + if (client->disconnectedCb) client->disconnectedCb(client); + if (client->cmdDisconnectedCb) client->cmdDisconnectedCb(client); // reconnect unless we're in a permanently disconnected state if (client->connState == MQTT_DISCONNECTED) return; @@ -547,10 +547,11 @@ msg_conn_init(mqtt_connection_t *new_msg, mqtt_connection_t *old_msg, * @retval TRUE if success queue */ bool ICACHE_FLASH_ATTR -MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, uint8_t qos, uint8_t retain) { +MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, uint16_t data_length, + uint8_t qos, uint8_t retain) +{ // estimate the packet size to allocate a buffer uint16_t topic_length = os_strlen(topic); - uint16_t data_length = os_strlen(data); // estimate: fixed hdr, pkt-id, topic length, topic, data, fudge uint16_t buf_len = 3 + 2 + 2 + topic_length + data_length + 16; PktBuf *buf = PktBuf_New(buf_len); @@ -738,8 +739,8 @@ mqtt_doAbort(MQTT_Client* client) { else espconn_disconnect(client->pCon); - if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client); - if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client); + if (client->disconnectedCb) client->disconnectedCb(client); + if (client->cmdDisconnectedCb) client->cmdDisconnectedCb(client); if (client->sending_buffer != NULL) { os_free(client->sending_buffer); diff --git a/mqtt/mqtt.h b/mqtt/mqtt.h index 0e98474..b5a99a5 100644 --- a/mqtt/mqtt.h +++ b/mqtt/mqtt.h @@ -44,14 +44,16 @@ typedef enum { MQTT_CONNECTED, // conneted (or connecting) } tConnState; +typedef struct MQTT_Client MQTT_Client; // forward definition + // Simple notification callback -typedef void (*MqttCallback)(uint32_t* args); +typedef void (*MqttCallback)(MQTT_Client *client); // Callback with data messge -typedef void (*MqttDataCallback)(uint32_t* args, const char* topic, uint32_t topic_len, +typedef void (*MqttDataCallback)(MQTT_Client *client, const char* topic, uint32_t topic_len, const char* data, uint32_t data_len); // MQTTY client data structure -typedef struct { +struct MQTT_Client { struct espconn* pCon; // socket // connection information char* host; // MQTT server @@ -89,7 +91,7 @@ typedef struct { MqttDataCallback cmdDataCb; // misc void* user_data; -} MQTT_Client; +}; // Initialize client data structure void MQTT_Init(MQTT_Client* mqttClient, char* host, uint32 port, @@ -119,7 +121,7 @@ void MQTT_Disconnect(MQTT_Client* mqttClient); bool MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos); // Publish a message -bool MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, +bool MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, uint16_t data_len, uint8_t qos, uint8_t retain); // Callback when connected diff --git a/mqtt/mqtt_cmd.c b/mqtt/mqtt_cmd.c index 4571f0a..05f277f 100644 --- a/mqtt/mqtt_cmd.c +++ b/mqtt/mqtt_cmd.c @@ -13,74 +13,51 @@ #define DBG(format, ...) do { } while(0) #endif -// if MQTT_1_CLIENT is defined we only support the one client that is built into esp-link. -// this keeps everything simpler. Undefining it brings back old code that supports creating -// a new client and setting all its params. Most likely that old code no longer works... -#define MQTT_1_CLIENT - -// callbacks to the attached uC -uint32_t connectedCb = 0, disconnectCb = 0, publishedCb = 0, dataCb = 0; - void ICACHE_FLASH_ATTR -cmdMqttConnectedCb(uint32_t* args) { - MQTT_Client* client = (MQTT_Client*)args; +cmdMqttConnectedCb(MQTT_Client* client) { MqttCmdCb* cb = (MqttCmdCb*)client->user_data; - DBG("MQTT: Connected connectedCb=%p, disconnectedCb=%p, publishedCb=%p, dataCb=%p\n", - (void*)cb->connectedCb, - (void*)cb->disconnectedCb, - (void*)cb->publishedCb, - (void*)cb->dataCb); - uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0); - cmdResponseEnd(crc); + DBG("MQTT: Connected Cb=%p\n", (void*)cb->connectedCb); + cmdResponseStart(CMD_RESP_CB, cb->connectedCb, 0); + cmdResponseEnd(); } void ICACHE_FLASH_ATTR -cmdMqttDisconnectedCb(uint32_t* args) { - MQTT_Client* client = (MQTT_Client*)args; +cmdMqttDisconnectedCb(MQTT_Client* client) { MqttCmdCb* cb = (MqttCmdCb*)client->user_data; - DBG("MQTT: Disconnected\n"); - uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0); - cmdResponseEnd(crc); + DBG("MQTT: Disconnected cb=%p\n", (void*)cb->disconnectedCb); + cmdResponseStart(CMD_RESP_CB, cb->disconnectedCb, 0); + cmdResponseEnd(); } void ICACHE_FLASH_ATTR -cmdMqttPublishedCb(uint32_t* args) { - MQTT_Client* client = (MQTT_Client*)args; +cmdMqttPublishedCb(MQTT_Client* client) { MqttCmdCb* cb = (MqttCmdCb*)client->user_data; - DBG("MQTT: Published\n"); - uint16_t crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0); - cmdResponseEnd(crc); + DBG("MQTT: Published cb=%p\n", (void*)cb->publishedCb); + cmdResponseStart(CMD_RESP_CB, cb->publishedCb, 0); + cmdResponseEnd(); } void ICACHE_FLASH_ATTR -cmdMqttDataCb(uint32_t* args, const char* topic, uint32_t topic_len, const char* data, uint32_t data_len) { - uint16_t crc = 0; - MQTT_Client* client = (MQTT_Client*)args; +cmdMqttDataCb(MQTT_Client* client, const char* topic, uint32_t topic_len, + const char* data, uint32_t data_len) +{ MqttCmdCb* cb = (MqttCmdCb*)client->user_data; + DBG("MQTT: Data cb=%p topic=%s len=%ld\n", (void*)cb->dataCb, topic, data_len); - crc = cmdResponseStart(CMD_MQTT_EVENTS, cb->dataCb, 0, 2); - crc = cmdResponseBody(crc, (uint8_t*)topic, topic_len); - crc = cmdResponseBody(crc, (uint8_t*)data, data_len); - cmdResponseEnd(crc); + cmdResponseStart(CMD_RESP_CB, cb->dataCb, 2); + cmdResponseBody(topic, topic_len); + cmdResponseBody(data, data_len); + cmdResponseEnd(); } -uint32_t ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR MQTTCMD_Lwt(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); - if (cmdGetArgc(&req) != 5) - return 0; + if (cmdGetArgc(&req) != 4) return; - // get mqtt client - uint32_t client_ptr; - cmdPopArg(&req, (uint8_t*)&client_ptr, 4); -#ifdef MQTT_1_CLIENT MQTT_Client* client = &mqttClient; -#else - MQTT_Client* client = (MQTT_Client*)client_ptr; - DBG("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr); -#endif // free old topic & message if (client->connect_info.will_topic) @@ -92,14 +69,14 @@ MQTTCMD_Lwt(CmdPacket *cmd) { // get topic len = cmdArgLen(&req); - if (len > 128) return 0; // safety check + if (len > 128) return; // safety check client->connect_info.will_topic = (char*)os_zalloc(len + 1); cmdPopArg(&req, client->connect_info.will_topic, len); client->connect_info.will_topic[len] = 0; // get message len = cmdArgLen(&req); - if (len > 128) return 0; // safety check + if (len > 128) return; // safety check client->connect_info.will_message = (char*)os_zalloc(len + 1); cmdPopArg(&req, client->connect_info.will_message, len); client->connect_info.will_message[len] = 0; @@ -118,32 +95,22 @@ MQTTCMD_Lwt(CmdPacket *cmd) { // trigger a reconnect to set the LWT MQTT_Reconnect(client); - return 1; } -uint32_t ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR MQTTCMD_Publish(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); - if (cmdGetArgc(&req) != 6) - return 0; + if (cmdGetArgc(&req) != 5) return; - // get mqtt client - uint32_t client_ptr; - cmdPopArg(&req, (uint8_t*)&client_ptr, 4); -#ifdef MQTT_1_CLIENT MQTT_Client* client = &mqttClient; -#else - MQTT_Client* client = (MQTT_Client*)client_ptr; - DBG("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr); -#endif uint16_t len; // get topic len = cmdArgLen(&req); - if (len > 128) return 0; // safety check + if (len > 128) return; // safety check uint8_t *topic = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, topic, len); topic[len] = 0; @@ -153,58 +120,46 @@ MQTTCMD_Publish(CmdPacket *cmd) { uint8_t *data = (uint8_t*)os_zalloc(len+1); if (!data) { // safety check os_free(topic); - return 0; + return; } cmdPopArg(&req, data, len); data[len] = 0; - uint32_t qos, retain, data_len; + uint16_t data_len; + uint8_t qos, retain; // get data length - // this isn't used but we have to pull it off the stack - cmdPopArg(&req, (uint8_t*)&data_len, 4); + cmdPopArg(&req, &data_len, sizeof(data_len)); // get qos - cmdPopArg(&req, (uint8_t*)&qos, 4); + cmdPopArg(&req, &qos, sizeof(qos)); // get retain - cmdPopArg(&req, (uint8_t*)&retain, 4); + cmdPopArg(&req, &retain, sizeof(retain)); - DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n", - topic, - os_strlen((char*)data), - qos, - retain); + DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%d, retain=%d\n", + topic, data_len, qos, retain); - MQTT_Publish(client, (char*)topic, (char*)data, (uint8_t)qos, (uint8_t)retain); + MQTT_Publish(client, (char*)topic, (char*)data, data_len, qos%3, retain&1); os_free(topic); os_free(data); - return 1; + return; } -uint32_t ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR MQTTCMD_Subscribe(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); - if (cmdGetArgc(&req) != 3) - return 0; + if (cmdGetArgc(&req) != 2) return; - // get mqtt client - uint32_t client_ptr; - cmdPopArg(&req, (uint8_t*)&client_ptr, 4); -#ifdef MQTT_1_CLIENT MQTT_Client* client = &mqttClient; -#else - MQTT_Client* client = (MQTT_Client*)client_ptr; - DBG("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr); -#endif uint16_t len; // get topic len = cmdArgLen(&req); - if (len > 128) return 0; // safety check + if (len > 128) return; // safety check uint8_t* topic = (uint8_t*)os_zalloc(len + 1); cmdPopArg(&req, topic, len); topic[len] = 0; @@ -217,22 +172,19 @@ MQTTCMD_Subscribe(CmdPacket *cmd) { MQTT_Subscribe(client, (char*)topic, (uint8_t)qos); os_free(topic); - return 1; + return; } -uint32_t ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR MQTTCMD_Setup(CmdPacket *cmd) { CmdRequest req; cmdRequest(&req, cmd); -#ifdef MQTT_1_CLIENT MQTT_Client* client = &mqttClient; - cmdSkipArg(&req); - cmdSkipArg(&req); - cmdSkipArg(&req); - cmdSkipArg(&req); - cmdSkipArg(&req); -#else + + if (cmdGetArgc(&req) != 4) return; + +#if 0 if (cmdGetArgc(&req) != 9) return 0; @@ -287,27 +239,28 @@ MQTTCMD_Setup(CmdPacket *cmd) { // create callback MqttCmdCb* callback = (MqttCmdCb*)os_zalloc(sizeof(MqttCmdCb)); - uint32_t cb_data; - - cmdPopArg(&req, (uint8_t*)&cb_data, 4); - callback->connectedCb = cb_data; - cmdPopArg(&req, (uint8_t*)&cb_data, 4); - callback->disconnectedCb = cb_data; - cmdPopArg(&req, (uint8_t*)&cb_data, 4); - callback->publishedCb = cb_data; - cmdPopArg(&req, (uint8_t*)&cb_data, 4); - callback->dataCb = cb_data; - + cmdPopArg(&req, &callback->connectedCb, 4); + cmdPopArg(&req, &callback->disconnectedCb, 4); + cmdPopArg(&req, &callback->publishedCb, 4); + cmdPopArg(&req, &callback->dataCb, 4); client->user_data = callback; + DBG("MQTT connectedCb=%lx\n", callback->connectedCb); + client->cmdConnectedCb = cmdMqttConnectedCb; client->cmdDisconnectedCb = cmdMqttDisconnectedCb; client->cmdPublishedCb = cmdMqttPublishedCb; client->cmdDataCb = cmdMqttDataCb; - return 0xf00df00d; //(uint32_t)client; + if (client->connState == MQTT_CONNECTED) { + if (callback->connectedCb) + cmdMqttConnectedCb(client); + } else if (callback->disconnectedCb) { + cmdMqttDisconnectedCb(client); + } } +#if 0 uint32_t ICACHE_FLASH_ATTR MQTTCMD_Connect(CmdPacket *cmd) { CmdRequest req; @@ -383,3 +336,4 @@ MQTTCMD_Disconnect(CmdPacket *cmd) { return 1; #endif } +#endif