Added Doxyfile. See full log.
Since this is my first "quasi-professional" project that I actually want others to use, I wanted there to be decent quality documentation for all the functions and structs that the end user would need to use. I had tried Doxygen before but never had much luck, mostly because I didn't bother to put in the effort to read the documentation closely. So this time around I did, and the output so far looks quite good and has a lot of detail about the functions, and the two typedef structs that are key to everything working. Added code to check if wifi is connected before allowing the TCP connection to be attempted. Similar code for mqtt_connect, checking if we have a valid TCP connection to the server. Waiting for wifi uses a new global timer. These changes affected the indentation of huge chunks of the code, as they got wrapped in ifs. We now take advantage of the void *reverse pointer in the espconn struct to point to the mqtt_session_t that is active. This is a nice touch that Espressif added, so you can access arbitrary data from within callbacks. This will allow us to (soon) have user callbacks to deal with MQTT messages. Also added license notices to all the source code files.
This commit is contained in:
parent
33cdfa54a9
commit
cfb041a679
7 changed files with 2819 additions and 236 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@ mqtt
|
||||||
\#*\#
|
\#*\#
|
||||||
.\#*
|
.\#*
|
||||||
pcap/
|
pcap/
|
||||||
|
docs/
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -1,3 +1,7 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
P=mqtt
|
P=mqtt
|
||||||
CC=xtensa-lx106-elf-gcc
|
CC=xtensa-lx106-elf-gcc
|
||||||
AR=xtensa-lx106-elf-ar
|
AR=xtensa-lx106-elf-ar
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# MQTT Library for ESP8266 SDK
|
# MQTT Library for ESP8266 SDK
|
||||||
written by Alexander Rowsell (MrAureliusR)
|
written by Alexander Rowsell (MrAureliusR)
|
||||||
Released under the terms of the MIT License -- see [LICENSE](LICENSE) for more detail.
|
Released under the terms of the Mozilla Public License v2.0 -- see [LICENSE](LICENSE) for more detail.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
While working on a series of tutorials for Hackaday, I realized MQTT would be the perfect solution for one of the projects I was presenting. However, I didn't want to use a pre-existing MQTT library - that would be boring, and I wouldn't be able to teach the readers as much. Instead, I started to write one from scratch.
|
While working on a series of tutorials for Hackaday, I realized MQTT would be the perfect solution for one of the projects I was presenting. However, I didn't want to use a pre-existing MQTT library - that would be boring, and I wouldn't be able to teach the readers as much. Instead, I started to write one from scratch.
|
||||||
|
|
423
mqtt.c
423
mqtt.c
|
@ -12,7 +12,6 @@
|
||||||
#include "os_type.h"
|
#include "os_type.h"
|
||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
|
||||||
/* Functions we will need to implement:
|
/* Functions we will need to implement:
|
||||||
* Send -- will handle all sending of all packets
|
* Send -- will handle all sending of all packets
|
||||||
* Connect -- set up TCP connection and parameters
|
* Connect -- set up TCP connection and parameters
|
||||||
|
@ -27,12 +26,15 @@ static os_timer_t oneTimer;
|
||||||
static os_timer_t testTimer;
|
static os_timer_t testTimer;
|
||||||
#endif
|
#endif
|
||||||
static os_timer_t MQTT_KeepAliveTimer;
|
static os_timer_t MQTT_KeepAliveTimer;
|
||||||
|
static os_timer_t waitForWifiTimer;
|
||||||
|
|
||||||
LOCAL void ICACHE_FLASH_ATTR data_sent_callback(void *arg) {
|
LOCAL void ICACHE_FLASH_ATTR data_sent_callback(void *arg) {
|
||||||
os_printf("Data sent!\n");
|
os_printf("Data sent!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) {
|
LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) {
|
||||||
|
struct espconn *pConn = arg;
|
||||||
|
mqtt_session_t *session = pConn->reverse;
|
||||||
// deal with received data
|
// deal with received data
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("Received data of length %d -- %s \r\n", len, pdata);
|
os_printf("Received data of length %d -- %s \r\n", len, pdata);
|
||||||
|
@ -82,11 +84,13 @@ LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned
|
||||||
case MQTT_MSG_TYPE_PINGRESP:
|
case MQTT_MSG_TYPE_PINGRESP:
|
||||||
os_printf("Pong!\n");
|
os_printf("Pong!\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg) {
|
LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg) {
|
||||||
struct espconn *pConn = arg;
|
struct espconn *pConn = arg;
|
||||||
|
mqtt_session_t *pSession = pConn->reverse;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("Connected callback\n");
|
os_printf("Connected callback\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -94,6 +98,7 @@ LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg) {
|
||||||
espconn_regist_sentcb(pConn, (espconn_sent_callback)data_sent_callback);
|
espconn_regist_sentcb(pConn, (espconn_sent_callback)data_sent_callback);
|
||||||
// enable keepalive
|
// enable keepalive
|
||||||
espconn_set_opt(pConn, ESPCONN_KEEPALIVE);
|
espconn_set_opt(pConn, ESPCONN_KEEPALIVE);
|
||||||
|
pSession->validConnection = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) {
|
LOCAL void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) {
|
||||||
|
@ -106,56 +111,57 @@ LOCAL void ICACHE_FLASH_ATTR disconnected_callback(void *arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) {
|
LOCAL uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) {
|
||||||
mqtt_session_t *session = arg;
|
os_timer_disarm(&waitForWifiTimer);
|
||||||
struct ip_info ipConfig;
|
struct ip_info ipConfig;
|
||||||
LOCAL struct espconn conn;
|
mqtt_session_t *session = arg;
|
||||||
LOCAL struct _esp_tcp tcp_s;
|
|
||||||
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipConfig.ip.addr != 0) {
|
|
||||||
os_printf("Everything looks good!\n");
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
os_printf("Entered tcpConnect\n");
|
|
||||||
#endif
|
|
||||||
wifi_get_ip_info(STATION_IF, &ipConfig);
|
wifi_get_ip_info(STATION_IF, &ipConfig);
|
||||||
// set up basic TCP connection parameters
|
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipConfig.ip.addr != 0) {
|
||||||
|
struct ip_info ipConfig;
|
||||||
|
|
||||||
|
LOCAL struct espconn conn;
|
||||||
|
LOCAL struct _esp_tcp tcp_s;
|
||||||
|
conn.reverse = arg;
|
||||||
|
os_printf("Everything looks good!\n");
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("about to set up TCP params\n");
|
os_printf("Entered tcpConnect\n");
|
||||||
#endif
|
#endif
|
||||||
conn.proto.tcp = &tcp_s;
|
wifi_get_ip_info(STATION_IF, &ipConfig);
|
||||||
conn.type = ESPCONN_TCP;
|
// set up basic TCP connection parameters
|
||||||
conn.proto.tcp->local_port = espconn_port();
|
#ifdef DEBUG
|
||||||
conn.proto.tcp->remote_port = session->port;
|
os_printf("about to set up TCP params\n");
|
||||||
conn.state = ESPCONN_NONE;
|
#endif
|
||||||
os_memcpy(conn.proto.tcp->remote_ip, session->ip, 4);
|
conn.proto.tcp = &tcp_s;
|
||||||
|
conn.type = ESPCONN_TCP;
|
||||||
os_printf("About to register callbacks\n");
|
conn.proto.tcp->local_port = espconn_port();
|
||||||
// register callbacks
|
conn.proto.tcp->remote_port = session->port;
|
||||||
espconn_regist_connectcb(&conn, (espconn_connect_callback)connected_callback);
|
conn.state = ESPCONN_NONE;
|
||||||
espconn_regist_reconcb(&conn, (espconn_reconnect_callback)reconnected_callback);
|
os_memcpy(conn.proto.tcp->remote_ip, session->ip, 4);
|
||||||
espconn_regist_disconcb(&conn, (espconn_connect_callback)disconnected_callback);
|
|
||||||
os_printf("About to connect\n");
|
os_printf("About to register callbacks\n");
|
||||||
//make the connection
|
// register callbacks
|
||||||
if(espconn_connect(&conn) == 0) {
|
espconn_regist_connectcb(&conn, (espconn_connect_callback)connected_callback);
|
||||||
os_printf("Connection successful\n");
|
espconn_regist_reconcb(&conn, (espconn_reconnect_callback)reconnected_callback);
|
||||||
} else {
|
espconn_regist_disconcb(&conn, (espconn_connect_callback)disconnected_callback);
|
||||||
os_printf("Connection error\n");
|
os_printf("About to connect\n");
|
||||||
|
//make the connection
|
||||||
|
if(espconn_connect(&conn) == 0) {
|
||||||
|
os_printf("Connection successful\n");
|
||||||
|
} else {
|
||||||
|
os_printf("Connection error\n");
|
||||||
|
}
|
||||||
|
session->activeConnection = &conn;
|
||||||
|
#ifdef DEBUG
|
||||||
|
os_printf("About to return from TCP connect\n");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// set timer to try again
|
||||||
|
os_timer_setfn(&waitForWifiTimer, (os_timer_func_t *)tcpConnect, session);
|
||||||
|
os_timer_arm(&waitForWifiTimer, 1000, 0);
|
||||||
}
|
}
|
||||||
session->activeConnection = &conn;
|
|
||||||
#ifdef DEBUG
|
|
||||||
os_printf("About to return from TCP connect\n");
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
|
||||||
/* Function: encodeLength */
|
|
||||||
/* Parameters: the length in bytes */
|
|
||||||
/* Returns: encoded multi-byte number per MQTT standards. The first byte this pointer */
|
|
||||||
/* returns is the number of bytes to follow. */
|
|
||||||
/* The MQTT standard uses a very strange method of encoding the lengths of the various sections */
|
|
||||||
/* of the packets. This makes it simpler to implement in code. */
|
|
||||||
/************************************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength) {
|
LOCAL uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength) {
|
||||||
uint8_t *encodedByte = os_zalloc(sizeof(uint8_t) * 5); // can't be more than 5 bytes
|
uint8_t *encodedByte = os_zalloc(sizeof(uint8_t) * 5); // can't be more than 5 bytes
|
||||||
|
@ -179,183 +185,176 @@ LOCAL void ICACHE_FLASH_ATTR pingAlive(void *arg) {
|
||||||
mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ);
|
mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* Function: mqtt_send */
|
|
||||||
/* Parameters: active mqtt_session_t, pointer to data, data length, and message type */
|
|
||||||
/* This function must do a few different things: */
|
|
||||||
/* * It must create the packet based on the message type and data */
|
|
||||||
/* * It must send the packet to the server */
|
|
||||||
/*************************************************************************************/
|
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType) {
|
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType) {
|
||||||
os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called
|
if(session->validConnection == 1) {
|
||||||
/** First thing to do is check the packet type.
|
os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called
|
||||||
* This will inform everything else we do
|
|
||||||
*/
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("Entering mqtt_send!\n");
|
os_printf("Entering mqtt_send!\n");
|
||||||
#endif
|
#endif
|
||||||
LOCAL mqtt_packet_t packet;
|
LOCAL mqtt_packet_t packet;
|
||||||
LOCAL mqtt_packet_t *pPacket = &packet;
|
LOCAL mqtt_packet_t *pPacket = &packet;
|
||||||
uint8_t *fullPacket;
|
uint8_t *fullPacket;
|
||||||
uint8_t *remaining_len_encoded;
|
uint8_t *remaining_len_encoded;
|
||||||
switch(msgType) {
|
switch(msgType) {
|
||||||
case MQTT_MSG_TYPE_CONNECT: {
|
case MQTT_MSG_TYPE_CONNECT: {
|
||||||
const uint8_t varDefaults[10] = { 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0xC2, 0x00, 0x32 }; // variable header is always the same for Connect
|
const uint8_t varDefaults[10] = { 0x00, 0x04, 0x4D, 0x51, 0x54, 0x54, 0x04, 0xC2, 0x00, 0x32 }; // variable header is always the same for Connect
|
||||||
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5); // fixed header cannot be longer than 5
|
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5); // fixed header cannot be longer than 5
|
||||||
pPacket->fixedHeader[0] = ((uint8_t)msgType << 4) & 0xF0; // make sure lower 4 are clear
|
pPacket->fixedHeader[0] = ((uint8_t)msgType << 4) & 0xF0; // make sure lower 4 are clear
|
||||||
// prepare variable header
|
// prepare variable header
|
||||||
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 10); // 10 bytes for connect
|
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 10); // 10 bytes for connect
|
||||||
os_memcpy(pPacket->varHeader, varDefaults, 10); // copy defaults
|
os_memcpy(pPacket->varHeader, varDefaults, 10); // copy defaults
|
||||||
pPacket->varHeader_len = 10;
|
pPacket->varHeader_len = 10;
|
||||||
// prepare payload
|
// prepare payload
|
||||||
uint32_t offset = 0; // keep track of how many bytes we have copied
|
uint32_t offset = 0; // keep track of how many bytes we have copied
|
||||||
uint32_t maxPayloadLength = session->client_id_len + session->username_len + session->password_len + 12; // length info can only take a maximum of 12 bytes
|
uint32_t maxPayloadLength = session->client_id_len + session->username_len + session->password_len + 12; // length info can only take a maximum of 12 bytes
|
||||||
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * maxPayloadLength);
|
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * maxPayloadLength);
|
||||||
// copy client id to payload: 2 bytes for size, then client id.
|
// copy client id to payload: 2 bytes for size, then client id.
|
||||||
// insert a 0
|
// insert a 0
|
||||||
os_memset(pPacket->payload + offset, 0, 1); // MSB is always 0
|
os_memset(pPacket->payload + offset, 0, 1); // MSB is always 0
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, &session->client_id_len, 1); // LSB is length of string
|
os_memcpy(pPacket->payload + offset, &session->client_id_len, 1); // LSB is length of string
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, session->client_id, session->client_id_len); // and copy string
|
os_memcpy(pPacket->payload + offset, session->client_id, session->client_id_len); // and copy string
|
||||||
offset += session->client_id_len;
|
offset += session->client_id_len;
|
||||||
// copy username to payload: same as client id, 2 bytes for size, then username
|
// copy username to payload: same as client id, 2 bytes for size, then username
|
||||||
// insert a 0
|
// insert a 0
|
||||||
os_memset(pPacket->payload + offset, 0, 1);
|
os_memset(pPacket->payload + offset, 0, 1);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, &session->username_len, 1);
|
os_memcpy(pPacket->payload + offset, &session->username_len, 1);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, session->username, session->username_len);
|
os_memcpy(pPacket->payload + offset, session->username, session->username_len);
|
||||||
offset += session->username_len;
|
offset += session->username_len;
|
||||||
// Password: same as username and client id, 2 bytes for size, then password
|
// Password: same as username and client id, 2 bytes for size, then password
|
||||||
// insert a 0
|
// insert a 0
|
||||||
os_memset(pPacket->payload + offset, 0, 1);
|
os_memset(pPacket->payload + offset, 0, 1);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, &session->password_len, 1);
|
os_memcpy(pPacket->payload + offset, &session->password_len, 1);
|
||||||
offset += 1;
|
offset += 1;
|
||||||
os_memcpy(pPacket->payload + offset, session->password, session->password_len);
|
os_memcpy(pPacket->payload + offset, session->password, session->password_len);
|
||||||
offset += session->password_len;
|
offset += session->password_len;
|
||||||
pPacket->payload_len = offset; // the length of the payload is the same as our offset
|
pPacket->payload_len = offset; // the length of the payload is the same as our offset
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("Total offset: %d\n", offset);
|
os_printf("Total offset: %d\n", offset);
|
||||||
#endif
|
#endif
|
||||||
// the remaining length is the size of the packet, minus the first byte and the bytes taken by the remaining length bytes themselves
|
// the remaining length is the size of the packet, minus the first byte and the bytes taken by the remaining length bytes themselves
|
||||||
// they are encoded per the MQTT spec, section 2.2.3
|
// they are encoded per the MQTT spec, section 2.2.3
|
||||||
// the first byte returned by encodeLength is the number of bytes to follow, as it can be anywhere from 1 to 4 bytes to encode the length
|
// the first byte returned by encodeLength is the number of bytes to follow, as it can be anywhere from 1 to 4 bytes to encode the length
|
||||||
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
||||||
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
||||||
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
||||||
// the full length is the length of the varHeader, payload, and fixedHeader
|
// the full length is the length of the varHeader, payload, and fixedHeader
|
||||||
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("Packet length: %d\n", pPacket->length);
|
os_printf("Packet length: %d\n", pPacket->length);
|
||||||
#endif
|
#endif
|
||||||
// construct packet data
|
// construct packet data
|
||||||
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
||||||
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case MQTT_MSG_TYPE_PUBLISH: {
|
||||||
|
// prepare for publish
|
||||||
|
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5);
|
||||||
|
pPacket->fixedHeader[0] = (MQTT_MSG_TYPE_PUBLISH << 4) & 0xF0; // clear lower 4 bits, we don't need DUP, QOS or RETAIN
|
||||||
|
|
||||||
|
// variable header
|
||||||
|
// A PUBLISH Packet MUST NOT contain a Packet Identifier if its QoS value is set to 0 [MQTT-2.3.1-5].
|
||||||
|
pPacket->varHeader_len = session->topic_name_len + 2; // we have no packet identifier, as we are QOS 0
|
||||||
|
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
|
||||||
|
os_memset(pPacket->varHeader, 0, 1);
|
||||||
|
os_memcpy(pPacket->varHeader + 1, &session->topic_name_len, 1);
|
||||||
|
os_memcpy(pPacket->varHeader + 2, session->topic_name, session->topic_name_len);
|
||||||
|
|
||||||
|
//payload
|
||||||
|
pPacket->payload_len = len;
|
||||||
|
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
|
||||||
|
os_memcpy(pPacket->payload, data, pPacket->payload_len);
|
||||||
|
// calculate remaining length for fixed header
|
||||||
|
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
||||||
|
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
||||||
|
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
||||||
|
// the full length is the length of the varHeader, payload, and fixedHeader
|
||||||
|
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
||||||
|
os_printf("Packet length: %d\n", pPacket->length);
|
||||||
|
// construct packet data
|
||||||
|
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
||||||
|
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
||||||
|
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
||||||
|
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MQTT_MSG_TYPE_SUBSCRIBE:
|
||||||
|
case MQTT_MSG_TYPE_UNSUBSCRIBE:
|
||||||
|
// prepare for subscribe
|
||||||
|
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5);
|
||||||
|
pPacket->fixedHeader[0] = ((msgType << 4) & 0xF0) | 0x02;
|
||||||
|
|
||||||
|
pPacket->varHeader_len = 2;
|
||||||
|
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
|
||||||
|
os_memset(pPacket->varHeader, 0, 2); // set packet ID to 0
|
||||||
|
|
||||||
|
uint8_t extraByte = (msgType == MQTT_MSG_TYPE_SUBSCRIBE) ? 3 : 2;
|
||||||
|
pPacket->payload_len = session->topic_name_len + extraByte;
|
||||||
|
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
|
||||||
|
pPacket->payload[1] = session->topic_name_len % 0xFF;
|
||||||
|
pPacket->payload[0] = session->topic_name_len / 0xFF;
|
||||||
|
os_memcpy(pPacket->payload + 2, session->topic_name, session->topic_name_len); // copy topic name
|
||||||
|
if(msgType == MQTT_MSG_TYPE_SUBSCRIBE) pPacket->payload[session->topic_name_len+2] = 0;
|
||||||
|
|
||||||
|
// calculate remaining length for fixed header
|
||||||
|
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
||||||
|
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
||||||
|
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
||||||
|
// the full length is the length of the varHeader, payload, and fixedHeader
|
||||||
|
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
||||||
|
os_printf("Packet length: %d\n", pPacket->length);
|
||||||
|
// construct packet data
|
||||||
|
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
||||||
|
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
||||||
|
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
||||||
|
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MQTT_MSG_TYPE_PINGREQ:
|
||||||
|
case MQTT_MSG_TYPE_DISCONNECT:
|
||||||
|
// PINGREQ has no varHeader or payload, it's just two bytes
|
||||||
|
// 0xC0 0x00
|
||||||
|
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 2);
|
||||||
|
pPacket->fixedHeader[0] = (msgType << 4) & 0xF0; // bottom nibble must be clear
|
||||||
|
pPacket->fixedHeader[1] = 0; // remaining length is zero
|
||||||
|
pPacket->fixedHeader_len = 2;
|
||||||
|
pPacket->length = pPacket->fixedHeader_len;
|
||||||
|
// In order to avoid undefined behaviour, we must allocate
|
||||||
|
// something to varHeader and payload, as they get passed
|
||||||
|
// to free() at the end of this function
|
||||||
|
pPacket->varHeader = (uint8_t *)os_zalloc(1);
|
||||||
|
pPacket->payload = (uint8_t *)os_zalloc(1);
|
||||||
|
// copy the fixedHeader to fullPacket, and we're done!
|
||||||
|
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
||||||
|
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// something has gone wrong
|
||||||
|
os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
case MQTT_MSG_TYPE_PUBLISH: {
|
|
||||||
// prepare for publish
|
|
||||||
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5);
|
|
||||||
pPacket->fixedHeader[0] = (MQTT_MSG_TYPE_PUBLISH << 4) & 0xF0; // clear lower 4 bits, we don't need DUP, QOS or RETAIN
|
|
||||||
|
|
||||||
// variable header
|
|
||||||
// A PUBLISH Packet MUST NOT contain a Packet Identifier if its QoS value is set to 0 [MQTT-2.3.1-5].
|
|
||||||
pPacket->varHeader_len = session->topic_name_len + 2; // we have no packet identifier, as we are QOS 0
|
|
||||||
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
|
|
||||||
os_memset(pPacket->varHeader, 0, 1);
|
|
||||||
os_memcpy(pPacket->varHeader + 1, &session->topic_name_len, 1);
|
|
||||||
os_memcpy(pPacket->varHeader + 2, session->topic_name, session->topic_name_len);
|
|
||||||
|
|
||||||
//payload
|
|
||||||
pPacket->payload_len = len;
|
|
||||||
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
|
|
||||||
os_memcpy(pPacket->payload, data, pPacket->payload_len);
|
|
||||||
// calculate remaining length for fixed header
|
|
||||||
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
|
||||||
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
|
||||||
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
|
||||||
// the full length is the length of the varHeader, payload, and fixedHeader
|
|
||||||
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
|
||||||
os_printf("Packet length: %d\n", pPacket->length);
|
|
||||||
// construct packet data
|
|
||||||
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
|
||||||
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MQTT_MSG_TYPE_SUBSCRIBE:
|
|
||||||
case MQTT_MSG_TYPE_UNSUBSCRIBE:
|
|
||||||
// prepare for subscribe
|
|
||||||
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5);
|
|
||||||
pPacket->fixedHeader[0] = ((msgType << 4) & 0xF0) | 0x02;
|
|
||||||
|
|
||||||
pPacket->varHeader_len = 2;
|
|
||||||
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
|
|
||||||
os_memset(pPacket->varHeader, 0, 2); // set packet ID to 0
|
|
||||||
|
|
||||||
uint8_t extraByte = (msgType == MQTT_MSG_TYPE_SUBSCRIBE) ? 3 : 2;
|
|
||||||
pPacket->payload_len = session->topic_name_len + extraByte;
|
|
||||||
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
|
|
||||||
pPacket->payload[1] = session->topic_name_len % 0xFF;
|
|
||||||
pPacket->payload[0] = session->topic_name_len / 0xFF;
|
|
||||||
os_memcpy(pPacket->payload + 2, session->topic_name, session->topic_name_len); // copy topic name
|
|
||||||
if(msgType == MQTT_MSG_TYPE_SUBSCRIBE) pPacket->payload[session->topic_name_len+2] = 0;
|
|
||||||
|
|
||||||
// calculate remaining length for fixed header
|
|
||||||
remaining_len_encoded = encodeLength((uint32_t)(pPacket->varHeader_len + pPacket->payload_len));
|
|
||||||
os_memcpy(pPacket->fixedHeader + 1, remaining_len_encoded + 1, remaining_len_encoded[0]);
|
|
||||||
pPacket->fixedHeader_len = remaining_len_encoded[0] + 1; // fixed header length is the number of bytes used to encode the remaining length, plus 1 for the fixed CONNECT byte
|
|
||||||
// the full length is the length of the varHeader, payload, and fixedHeader
|
|
||||||
pPacket->length = (pPacket->varHeader_len + pPacket->payload_len + pPacket->fixedHeader_len);
|
|
||||||
os_printf("Packet length: %d\n", pPacket->length);
|
|
||||||
// construct packet data
|
|
||||||
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
|
||||||
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len, pPacket->varHeader, pPacket->varHeader_len);
|
|
||||||
os_memcpy(fullPacket + pPacket->fixedHeader_len + pPacket->varHeader_len, pPacket->payload, pPacket->payload_len);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case MQTT_MSG_TYPE_PINGREQ:
|
|
||||||
case MQTT_MSG_TYPE_DISCONNECT:
|
|
||||||
// PINGREQ has no varHeader or payload, it's just two bytes
|
|
||||||
// 0xC0 0x00
|
|
||||||
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 2);
|
|
||||||
pPacket->fixedHeader[0] = (msgType << 4) & 0xF0; // bottom nibble must be clear
|
|
||||||
pPacket->fixedHeader[1] = 0; // remaining length is zero
|
|
||||||
pPacket->fixedHeader_len = 2;
|
|
||||||
pPacket->length = pPacket->fixedHeader_len;
|
|
||||||
// In order to avoid undefined behaviour, we must allocate
|
|
||||||
// something to varHeader and payload, as they get passed
|
|
||||||
// to free() at the end of this function
|
|
||||||
pPacket->varHeader = (uint8_t *)os_zalloc(1);
|
|
||||||
pPacket->payload = (uint8_t *)os_zalloc(1);
|
|
||||||
// copy the fixedHeader to fullPacket, and we're done!
|
|
||||||
fullPacket = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->length);
|
|
||||||
os_memcpy(fullPacket, pPacket->fixedHeader, pPacket->fixedHeader_len);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// something has gone wrong
|
|
||||||
os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
os_printf("About to send MQTT command type: %d...\n", (uint8_t)msgType);
|
os_printf("About to send MQTT command type: %d...\n", (uint8_t)msgType);
|
||||||
#endif
|
#endif
|
||||||
espconn_send(session->activeConnection, fullPacket, pPacket->length);
|
espconn_send(session->activeConnection, fullPacket, pPacket->length);
|
||||||
os_free(fullPacket);
|
os_free(fullPacket);
|
||||||
os_free(pPacket->fixedHeader);
|
os_free(pPacket->fixedHeader);
|
||||||
os_free(pPacket->varHeader);
|
os_free(pPacket->varHeader);
|
||||||
os_free(pPacket->payload);
|
os_free(pPacket->payload);
|
||||||
// set up keepalive timer
|
// set up keepalive timer
|
||||||
if(msgType != MQTT_MSG_TYPE_DISCONNECT) {
|
if(msgType != MQTT_MSG_TYPE_DISCONNECT) {
|
||||||
os_timer_setfn(&MQTT_KeepAliveTimer, (os_timer_func_t *)pingAlive, session);
|
os_timer_setfn(&MQTT_KeepAliveTimer, (os_timer_func_t *)pingAlive, session);
|
||||||
os_timer_arm(&MQTT_KeepAliveTimer, 5000, 0);
|
os_timer_arm(&MQTT_KeepAliveTimer, 30000, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
os_printf("No wifi! Narf!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +445,7 @@ void ICACHE_FLASH_ATTR user_init() {
|
||||||
static const uint8_t testTopic_len = 37;
|
static const uint8_t testTopic_len = 37;
|
||||||
//static const char testTopic[4] = { 0x74, 0x65, 0x73, 0x74 };
|
//static const char testTopic[4] = { 0x74, 0x65, 0x73, 0x74 };
|
||||||
//static const uint8_t testTopic_len = 4;
|
//static const uint8_t testTopic_len = 4;
|
||||||
static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 };
|
static const char clientID[5] = { 0x46, 0x5a, 0x5a, 0x4e, 0x30 };
|
||||||
static const uint8_t clientID_len = 5;
|
static const uint8_t clientID_len = 5;
|
||||||
pGlobalSession->port = 1883; // mqtt port
|
pGlobalSession->port = 1883; // mqtt port
|
||||||
static const char esp_tcp_server_ip[4] = {52, 5, 238, 97};
|
static const char esp_tcp_server_ip[4] = {52, 5, 238, 97};
|
||||||
|
|
121
mqtt.h
121
mqtt.h
|
@ -1,9 +1,33 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/********************************************************************************/
|
||||||
|
/* Some portions of this file were taken from the NodeMCU firmware project, */
|
||||||
|
/* at https://github.com/nodemcu/nodemcu-firmware. The original author is */
|
||||||
|
/* listed as "zeroday nodemcu.com". The code was licensed under the MIT */
|
||||||
|
/* license, which allows me to relicense it under the MPL, which I have done. */
|
||||||
|
/********************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief This is the main header file for all MQTT/TCP related functions.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "user_interface.h"
|
#include "user_interface.h"
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "osapi.h"
|
#include "osapi.h"
|
||||||
#include "espconn.h"
|
#include "espconn.h"
|
||||||
#include "os_type.h"
|
#include "os_type.h"
|
||||||
|
|
||||||
|
#define DEBUG 1 /**< This define enables or disables serial debug output in most places */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef
|
||||||
|
* This is the enum for message types.
|
||||||
|
*
|
||||||
|
* This enum was taken from the NodeMCU mqtt headers. Credit is given to "zeroday" of nodemcu.com. This enum gives us both easily readable names for each message type, but also the correct value for each type. These are used in mqtt_send() to construct the correct packet type.
|
||||||
|
*/
|
||||||
typedef enum mqtt_message_enum
|
typedef enum mqtt_message_enum
|
||||||
{
|
{
|
||||||
MQTT_MSG_TYPE_CONNECT = 1,
|
MQTT_MSG_TYPE_CONNECT = 1,
|
||||||
|
@ -22,41 +46,92 @@ typedef enum mqtt_message_enum
|
||||||
MQTT_MSG_TYPE_DISCONNECT = 14
|
MQTT_MSG_TYPE_DISCONNECT = 14
|
||||||
} mqtt_message_type;
|
} mqtt_message_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct mqtt_packet_t
|
||||||
|
* A structure which contains all the information for an MQTT packet.
|
||||||
|
*
|
||||||
|
* This structure contains pointers to the three main parts of an MQTT packet: the fixed header, the variable header, and the payload. Not all message types contain a variable header or payload, but *all* message types have a fixed header.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *fixedHeader;
|
uint8_t *fixedHeader; /**< The pointer to the fixed header bytes */
|
||||||
uint32_t fixedHeader_len;
|
uint32_t fixedHeader_len; /**< The length of the fixed header */
|
||||||
uint8_t *varHeader;
|
uint8_t *varHeader; /**< The pointer to the variable header bytes */
|
||||||
uint32_t varHeader_len;
|
uint32_t varHeader_len; /**< The length of the variable header */
|
||||||
uint8_t *payload;
|
uint8_t *payload; /**< The pointer to the payload bytes */
|
||||||
uint32_t payload_len;
|
uint32_t payload_len; /**< The length of the payload */
|
||||||
uint32_t length;
|
uint32_t length; /**< The full length of the packet */
|
||||||
mqtt_message_type msgType;
|
mqtt_message_type msgType; /**< What message type this packet contains */
|
||||||
} mqtt_packet_t;
|
} mqtt_packet_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct mqtt_session_t
|
||||||
|
* Structure that contains all the information to establish and maintain a TCP-based MQTT connection to the broker
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ip[4];
|
uint8_t ip[4]; /**< An array containing the four bytes of the IP address of the broker */
|
||||||
uint32_t port;
|
uint32_t port; /**< The port the broker is listening on */
|
||||||
uint32_t localPort;
|
uint32_t localPort; /**< The local port returned by the ESP8266 function espconn_port() */
|
||||||
uint8_t *client_id;
|
uint8_t *client_id; /**< Pointer to the client ID string */
|
||||||
uint32_t client_id_len;
|
uint32_t client_id_len; /**< Length of the client ID string */
|
||||||
uint8_t *topic_name;
|
uint8_t *topic_name; /**< Pointer to the topic name string */
|
||||||
uint32_t topic_name_len;
|
uint32_t topic_name_len; /**< Length of the topic name string */
|
||||||
uint8_t qos_level;
|
uint8_t qos_level; /**< QOS level of the MQTT connection (always 0, not currently used) */
|
||||||
uint8_t *username;
|
uint8_t *username; /**< Pointer to the username string, for brokers which require authentication */
|
||||||
uint32_t username_len;
|
uint32_t username_len; /**< The length of the username string */
|
||||||
uint8_t *password;
|
uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */
|
||||||
uint32_t password_len;
|
uint32_t password_len; /**< The length of the password string */
|
||||||
char valid_connection;
|
char validConnection; /**< Boolean value which indicates whether or not the TCP connection is established, set in tcpConnect() */
|
||||||
struct espconn *activeConnection;
|
struct espconn *activeConnection; /**< A pointer to the espconn structure containing details of the TCP connection */
|
||||||
} mqtt_session_t;
|
} mqtt_session_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function which initiates the connection to the TCP server.
|
||||||
|
* @param arg A pointer to void, so it can be called from a timer or task
|
||||||
|
* @return 0 on success
|
||||||
|
*/
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg);
|
LOCAL uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg);
|
||||||
LOCAL void ICACHE_FLASH_ATTR disconnected_callback(void *arg);
|
LOCAL void ICACHE_FLASH_ATTR disconnected_callback(void *arg);
|
||||||
LOCAL void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err);
|
LOCAL void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function which is called when TCP connection is successful.
|
||||||
|
* @param *arg A pointer to void, which needs to be cast to espconn *pConn
|
||||||
|
* @returns Void
|
||||||
|
*
|
||||||
|
* This function is called once the TCP connection to the server is completed. This allows us to register the callbacks for received and sent data, as well as enable TCP keepalive and set validConnection in mqtt_session_t to 1 to show the connection has been successful.
|
||||||
|
*/
|
||||||
LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg);
|
LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback function that deals with received data.
|
||||||
|
* @param *arg A pointer to void, which needs to be cast to espconn *pConn
|
||||||
|
* @param *pdata A pointer to the received data blob
|
||||||
|
* @param len The length of *pdata
|
||||||
|
* @return Void
|
||||||
|
*
|
||||||
|
* At this point the function does little more than detect what type of MQTT message is sent, and prints out debug info to the serial port. The next few versions should improve this so the user can register their own callback functions which will be called when the particular message type is receieved.
|
||||||
|
*/
|
||||||
LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len);
|
LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len);
|
||||||
LOCAL void ICACHE_FLASH_ATTR data_sent_callback(void *arg);
|
LOCAL void ICACHE_FLASH_ATTR data_sent_callback(void *arg);
|
||||||
LOCAL void ICACHE_FLASH_ATTR pingAlive(void *arg);
|
LOCAL void ICACHE_FLASH_ATTR pingAlive(void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function which takes a uint32_t and returns a pointer to a properly formatted MQTT length.
|
||||||
|
* @param trueLength the length in bytes
|
||||||
|
* @return encoded multi-byte number per MQTT standards. The first byte this pointer
|
||||||
|
* returns is the number of bytes to follow.
|
||||||
|
|
||||||
|
* The MQTT standard uses a very strange method of encoding the lengths of the various sections
|
||||||
|
* of the packets. This makes it simpler to implement in code.
|
||||||
|
*/
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength);
|
LOCAL uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function handles all the sending of various MQTT messages.
|
||||||
|
* @param session a pointer to the active mqtt_session_t
|
||||||
|
* @param data a pointer to the data to be published; only applied to MQTT_MSG_TYPE_PUBLISH
|
||||||
|
* @param len the length of the above data
|
||||||
|
* @param msgType the type of message to be send, one of the mqtt_message_type
|
||||||
|
* @return -1 in case of error, 0 otherwise
|
||||||
|
*/
|
||||||
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType);
|
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType);
|
||||||
|
|
10
strtoarr.py
10
strtoarr.py
|
@ -1,5 +1,15 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
##
|
||||||
|
# @file
|
||||||
|
# @brief File to create string arrays
|
||||||
|
#
|
||||||
|
# This file is included to assist the developer using the API in creating the arrays for the username, password, topic name, and client ID strings. It prints both the array itself as well as a variable with the length of the string. These can then be passed to os_memcpy() to copy the information into the mqtt_session_t.
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# First argument is the value to be encoded, #
|
# First argument is the value to be encoded, #
|
||||||
# second argument is the name of the variable #
|
# second argument is the name of the variable #
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue