Updated formatting with astyle -A14 -S

Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>
This commit is contained in:
A.M. Rowsell 2019-03-04 12:58:17 -05:00
commit 7c5dfae57b
Signed by: amr
GPG key ID: 0B6E2D8375CF79A9
7 changed files with 651 additions and 638 deletions

View file

@ -8,3 +8,5 @@ While working on a series of tutorials for Hackaday, I realized MQTT would be th
At this point, it's a bit messy. It still needs a lot of work. This documentation will help me keep everything organized and easy-to-use. At this point, it's a bit messy. It still needs a lot of work. This documentation will help me keep everything organized and easy-to-use.
The documentation has now been turned into Doxygen documentation. You can view the latest documentation [here](https://mraureliusr.gitlab.io/mqtt-esp8266/index.html) The documentation has now been turned into Doxygen documentation. You can view the latest documentation [here](https://mraureliusr.gitlab.io/mqtt-esp8266/index.html)
Make sure to check out the corresponding hackaday.io project!

20
dht.c
View file

@ -8,20 +8,20 @@
#define DHTBus BIT4 #define DHTBus BIT4
LOCAL uint8_t ICACHE_FLASH_ATTR getBitNum(uint32_t bit) { LOCAL uint8_t ICACHE_FLASH_ATTR getBitNum(uint32_t bit) {
uint32_t localBit = bit; uint32_t localBit = bit;
for(uint8_t i = 0; i <= 16; i++) { for(uint8_t i = 0; i <= 16; i++) {
localBit >>= i; localBit >>= i;
if(bit & 0x01) { if(bit & 0x01) {
return i; return i;
}
} }
} return -1; // if we reached this spot we received a bad number
return -1; // if we reached this spot we received a bad number
} }
void ICACHE_FLASH_ATTR setupDHT(void) { void ICACHE_FLASH_ATTR setupDHT(void) {
gpio_output_set(0, DHTBus, 0, DHTBus); // set up DHTBus as active low output gpio_output_set(0, DHTBus, 0, DHTBus); // set up DHTBus as active low output
ETS_GPIO_INTR_ATTACH(func, NULL); ETS_GPIO_INTR_ATTACH(func, NULL);
} }
void ICACHE_FLASH_ATTR getDHTData(void) { void ICACHE_FLASH_ATTR getDHTData(void) {
} }

236
main.c
View file

@ -14,144 +14,160 @@ os_timer_t pingTimer;
os_timer_t pubTimer; os_timer_t pubTimer;
LOCAL void ICACHE_FLASH_ATTR con(void *arg) { LOCAL void ICACHE_FLASH_ATTR con(void *arg) {
os_printf("Entered con!\n"); #ifdef DEBUG
mqtt_session_t *pSession = (mqtt_session_t *)arg; os_printf("Entered con!\n");
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT); #endif
mqtt_session_t *pSession = (mqtt_session_t *)arg;
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT);
os_timer_disarm(&pingTimer); os_timer_disarm(&pingTimer);
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg);
os_timer_arm(&pingTimer, 1000, 0); os_timer_arm(&pingTimer, 1000, 0);
} }
LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg) { LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg) {
os_printf("Entered pubuint!\n"); #ifdef DEBUG
mqtt_session_t *pSession = (mqtt_session_t *)arg; os_printf("Entered pubuint!\n");
uint8_t *data = (uint8_t *)(pSession->userData); #endif
char *dataStr = os_zalloc(20 * sizeof(char)); mqtt_session_t *pSession = (mqtt_session_t *)arg;
intToStr(*data, dataStr, 4); uint8_t *data = (uint8_t *)(pSession->userData);
int32_t dataLen = os_strlen(dataStr); char *dataStr = os_zalloc(20 * sizeof(char));
mqttSend(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH); intToStr(*data, dataStr, 4);
os_timer_disarm(&pingTimer); int32_t dataLen = os_strlen(dataStr);
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); mqttSend(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH);
os_timer_arm(&pingTimer, 1000, 0); os_timer_disarm(&pingTimer);
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg);
os_timer_arm(&pingTimer, 1000, 0);
} }
LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg) { LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg) {
os_printf("Entered pubfloat!\n"); #ifdef DEBUG
mqtt_session_t *pSession = (mqtt_session_t *)arg; os_printf("Entered pubfloat!\n");
float *data = (float *)(pSession->userData); #endif
char *dataStr = os_zalloc(20 * sizeof(char)); mqtt_session_t *pSession = (mqtt_session_t *)arg;
ftoa(*data, dataStr, 2); float *data = (float *)(pSession->userData);
int32_t dataLen = os_strlen(dataStr); char *dataStr = os_zalloc(20 * sizeof(char));
os_printf("Encoded string: %s\tString length: %d\n", dataStr, dataLen); ftoa(*data, dataStr, 2);
mqttSend(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH); int32_t dataLen = os_strlen(dataStr);
os_timer_disarm(&pingTimer); #ifdef DEBUG
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); os_printf("Encoded string: %s\tString length: %d\n", dataStr, dataLen);
os_timer_arm(&pingTimer, 1000, 0); #endif
mqttSend(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH);
os_timer_disarm(&pingTimer);
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg);
os_timer_arm(&pingTimer, 1000, 0);
} }
LOCAL void ICACHE_FLASH_ATTR ping(void *arg) { LOCAL void ICACHE_FLASH_ATTR ping(void *arg) {
#ifdef DEBUG #ifdef DEBUG
os_printf("Entered ping!\n"); os_printf("Entered ping!\n");
#endif #endif
mqtt_session_t *pSession = (mqtt_session_t *)arg; mqtt_session_t *pSession = (mqtt_session_t *)arg;
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ);
os_timer_disarm(&pingTimer); os_timer_disarm(&pingTimer);
os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg);
os_timer_arm(&pingTimer, 1000, 0); os_timer_arm(&pingTimer, 1000, 0);
} }
LOCAL void ICACHE_FLASH_ATTR sub(void *arg) { LOCAL void ICACHE_FLASH_ATTR sub(void *arg) {
os_printf("Entered sub!\n"); #ifdef DEBUG
mqtt_session_t *pSession = (mqtt_session_t *)arg; os_printf("Entered sub!\n");
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_SUBSCRIBE); #endif
mqtt_session_t *pSession = (mqtt_session_t *)arg;
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_SUBSCRIBE);
} }
LOCAL void ICACHE_FLASH_ATTR discon(void *arg) { LOCAL void ICACHE_FLASH_ATTR discon(void *arg) {
os_printf("Entered discon!\n"); #ifdef DEBUG
mqtt_session_t *pSession = (mqtt_session_t *)arg; os_printf("Entered discon!\n");
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT); #endif
os_timer_disarm(&pingTimer); mqtt_session_t *pSession = (mqtt_session_t *)arg;
os_timer_disarm(&pubTimer); mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT);
os_timer_disarm(&pingTimer);
os_timer_disarm(&pubTimer);
} }
LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) {
mqtt_session_t *pSession = (mqtt_session_t *)arg; mqtt_session_t *pSession = (mqtt_session_t *)arg;
oneWire_t DS18; oneWire_t DS18;
oneWire_t *pDS18 = &DS18; oneWire_t *pDS18 = &DS18;
uint16_t temp = 0; uint16_t temp = 0;
sint32 time = 0; sint32 time = 0;
pDS18->temperature = 0; pDS18->temperature = 0;
reset(); reset();
transact(pDS18, SKIP_ROM); transact(pDS18, SKIP_ROM);
transact(pDS18, CONVERT_T); transact(pDS18, CONVERT_T);
time = system_get_time() + 750000; time = system_get_time() + 750000;
while(system_get_time() < time); while(system_get_time() < time);
reset(); reset();
transact(pDS18, SKIP_ROM); transact(pDS18, SKIP_ROM);
transact(pDS18, SCRATCH_READ); transact(pDS18, SCRATCH_READ);
//os_printf("\nReceived onewire data: %x %x\n", pDS18->scratchpad[0], pDS18->scratchpad[1]); #ifdef DEBUG
temp = ((uint16_t)pDS18->scratchpad[1] << 8) | pDS18->scratchpad[0]; os_printf("\nReceived onewire data: %x %x\n", pDS18->scratchpad[0], pDS18->scratchpad[1]);
pDS18->temperature += (temp >> 4) + ((temp & 0x0F) * 0.0625); #endif
pSession->userData = (void *)&pDS18->temperature; temp = ((uint16_t)pDS18->scratchpad[1] << 8) | pDS18->scratchpad[0];
os_printf("\nTemperature is: %d.%02d\n", (int)pDS18->temperature, (int)(pDS18->temperature * 100) % 100); pDS18->temperature += (temp >> 4) + ((temp & 0x0F) * 0.0625);
pubfloat(pSession); // publish the temperature pSession->userData = (void *)&pDS18->temperature;
//discon(pSession); #ifdef DEBUG
return; os_printf("\nTemperature is: %d.%02d\n", (int)pDS18->temperature, (int)(pDS18->temperature * 100) % 100);
#endif
pubfloat(pSession); // publish the temperature
//discon(pSession);
return;
} }
void ICACHE_FLASH_ATTR user_init() { void ICACHE_FLASH_ATTR user_init() {
LOCAL mqtt_session_t globalSession; LOCAL mqtt_session_t globalSession;
LOCAL mqtt_session_t *pGlobalSession = &globalSession; LOCAL mqtt_session_t *pGlobalSession = &globalSession;
char ssid[32] = "yourwifissid"; char ssid[32] = "yourwifissid";
char passkey[64] = "yourwifipass"; char passkey[64] = "yourwifipass";
struct station_config stationConf; struct station_config stationConf;
gpio_init(); // init gpio so we can use the LED & onewire bus gpio_init(); // init gpio so we can use the LED & onewire bus
uart_div_modify(0, UART_CLK_FREQ / 921600); // set UART to 921600 uart_div_modify(0, UART_CLK_FREQ / 921600); // set UART to 921600
wifi_status_led_install(0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); // set GPIO0 as status LED wifi_status_led_install(0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); // set GPIO0 as status LED
stationConf.bssid_set = 0; stationConf.bssid_set = 0;
os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct
os_memcpy(&stationConf.password, passkey, 64); os_memcpy(&stationConf.password, passkey, 64);
wifi_set_opmode_current(0x01); //station mode wifi_set_opmode_current(0x01); //station mode
wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well
// prepare the TCP/MQTT connection stuff // prepare the TCP/MQTT connection stuff
// Adafruit IO is at 52.5.238.97 // Adafruit IO is at 52.5.238.97
// use strtoarr.py to generate these // use strtoarr.py to generate these
static const char ioUser[11] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52 }; // MrAureliusR static const char ioUser[11] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52 }; // MrAureliusR
static const uint8_t ioUser_len = 11; static const uint8_t ioUser_len = 11;
static const char ioKey[32] = { }; // use strtoarr.py to generate these static const char ioKey[32] = { }; // use strtoarr.py to generate these
static const uint8_t ioKey_len = 32; static const uint8_t ioKey_len = 32;
static const char ioTopic[27] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x74, 0x6f, 0x70, 0x69, 0x63 }; // MrAureliusR/feeds/testtopic static const char ioTopic[27] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x74, 0x6f, 0x70, 0x69, 0x63 }; // MrAureliusR/feeds/testtopic
static const uint8_t ioTopic_len = 27; static const uint8_t ioTopic_len = 27;
static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0
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 adafruitIO_ip[4] = {52, 5, 238, 97}; static const char adafruitIO_ip[4] = {52, 5, 238, 97};
// copy all the above info into our mqtt_session_t // copy all the above info into our mqtt_session_t
os_memcpy(pGlobalSession->ip, adafruitIO_ip, 4); os_memcpy(pGlobalSession->ip, adafruitIO_ip, 4);
pGlobalSession->username_len = ioUser_len; pGlobalSession->username_len = ioUser_len;
pGlobalSession->username = os_zalloc(sizeof(uint8_t) * pGlobalSession->username_len); pGlobalSession->username = os_zalloc(sizeof(uint8_t) * pGlobalSession->username_len);
os_memcpy(pGlobalSession->username, ioUser, pGlobalSession->username_len); os_memcpy(pGlobalSession->username, ioUser, pGlobalSession->username_len);
pGlobalSession->password_len = ioKey_len; pGlobalSession->password_len = ioKey_len;
pGlobalSession->password = os_zalloc(sizeof(uint8_t) * pGlobalSession->password_len); pGlobalSession->password = os_zalloc(sizeof(uint8_t) * pGlobalSession->password_len);
os_memcpy(pGlobalSession->password, ioKey, pGlobalSession->password_len); os_memcpy(pGlobalSession->password, ioKey, pGlobalSession->password_len);
pGlobalSession->topic_name_len = ioTopic_len; pGlobalSession->topic_name_len = ioTopic_len;
pGlobalSession->topic_name = os_zalloc(sizeof(uint8_t) * pGlobalSession->topic_name_len); pGlobalSession->topic_name = os_zalloc(sizeof(uint8_t) * pGlobalSession->topic_name_len);
os_memcpy(pGlobalSession->topic_name, ioTopic, pGlobalSession->topic_name_len); os_memcpy(pGlobalSession->topic_name, ioTopic, pGlobalSession->topic_name_len);
pGlobalSession->client_id_len = clientID_len; pGlobalSession->client_id_len = clientID_len;
pGlobalSession->client_id = os_zalloc(sizeof(uint8_t) * pGlobalSession->client_id_len); pGlobalSession->client_id = os_zalloc(sizeof(uint8_t) * pGlobalSession->client_id_len);
os_memcpy(pGlobalSession->client_id, clientID, pGlobalSession->client_id_len); os_memcpy(pGlobalSession->client_id, clientID, pGlobalSession->client_id_len);
// set up all the timers to connect and log data // set up all the timers to connect and log data
os_timer_setfn(&tcpTimer, (os_timer_func_t *)tcpConnect, pGlobalSession); os_timer_setfn(&tcpTimer, (os_timer_func_t *)tcpConnect, pGlobalSession);
os_timer_arm(&tcpTimer, 12000, 0); os_timer_arm(&tcpTimer, 12000, 0);
os_timer_setfn(&pingTimer, (os_timer_func_t *)con, pGlobalSession); os_timer_setfn(&pingTimer, (os_timer_func_t *)con, pGlobalSession);
os_timer_arm(&pingTimer, 16000, 0); os_timer_arm(&pingTimer, 16000, 0);
os_timer_setfn(&pubTimer, (os_timer_func_t *)dataLog, pGlobalSession); os_timer_setfn(&pubTimer, (os_timer_func_t *)dataLog, pGlobalSession);
os_timer_arm(&pubTimer, 20000, 1); os_timer_arm(&pubTimer, 20000, 1);
} }

738
mqtt.c
View file

@ -25,423 +25,419 @@
*/ */
static os_timer_t MQTT_KeepAliveTimer; static os_timer_t MQTT_KeepAliveTimer;
static os_timer_t waitForWifiTimer; static os_timer_t waitForWifiTimer;
// reverses a string 'str' of length 'len' // reverses a string 'str' of length 'len'
void reverse(char *str, int len) void reverse(char *str, int len) {
{ int i=0, j=len-1, temp;
int i=0, j=len-1, temp; while (i<j) {
while (i<j) temp = str[i];
{ str[i] = str[j];
temp = str[i]; str[j] = temp;
str[i] = str[j]; i++;
str[j] = temp; j--;
i++; j--; }
} }
}
// Converts a given integer x to string str[]. d is the number
// Converts a given integer x to string str[]. d is the number // of digits required in output. If d is more than the number
// of digits required in output. If d is more than the number // of digits in x, then 0s are added at the beginning.
// of digits in x, then 0s are added at the beginning. int intToStr(int x, char str[], int d) {
int intToStr(int x, char str[], int d) int i = 0;
{ while (x) {
int i = 0; str[i++] = (x%10) + '0';
while (x) x = x/10;
{ }
str[i++] = (x%10) + '0';
x = x/10; // If number of digits required is more, then
} // add 0s at the beginning
while (i < d)
// If number of digits required is more, then str[i++] = '0';
// add 0s at the beginning
while (i < d) reverse(str, i);
str[i++] = '0'; str[i] = '\0';
return i;
reverse(str, i); }
str[i] = '\0';
return i; // Converts a floating point number to string.
} void ftoa(float n, char *res, int afterpoint) {
// Extract integer part
// Converts a floating point number to string. int ipart = (int)n;
void ftoa(float n, char *res, int afterpoint)
{ // Extract floating part
// Extract integer part float fpart = n - (float)ipart;
int ipart = (int)n;
// convert integer part to string
// Extract floating part int i = intToStr(ipart, res, 0);
float fpart = n - (float)ipart;
// check for display option after point
// convert integer part to string if (afterpoint != 0) {
int i = intToStr(ipart, res, 0); res[i] = '.'; // add dot
// check for display option after point // Get the value of fraction part upto given no.
if (afterpoint != 0) // of points after dot. The third parameter is needed
{ // to handle cases like 233.007
res[i] = '.'; // add dot fpart = fpart * pow(10, afterpoint);
// Get the value of fraction part upto given no. intToStr((int)fpart, res + i + 1, afterpoint);
// of points after dot. The third parameter is needed }
// to handle cases like 233.007 }
fpart = fpart * pow(10, afterpoint);
intToStr((int)fpart, res + i + 1, afterpoint);
}
}
void ICACHE_FLASH_ATTR data_sent_callback(void *arg) { void ICACHE_FLASH_ATTR data_sent_callback(void *arg) {
#ifdef DEBUG #ifdef DEBUG
os_printf("Data sent!\n"); os_printf("Data sent!\n");
#endif #endif
return; return;
} }
void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) { void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) {
struct espconn *pConn = arg; struct espconn *pConn = arg;
mqtt_session_t *session = pConn->reverse; 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);
os_printf("Hex dump: "); os_printf("Hex dump: ");
for(int i = 0; i < len; i++) { for(int i = 0; i < len; i++) {
os_printf("(%d): %x ", i, pdata[i]); os_printf("(%d): %x ", i, pdata[i]);
} }
os_printf("\n"); os_printf("\n");
#endif #endif
mqtt_message_type msgType = ((mqtt_message_type)pdata[0] >> 4) & 0x0F; mqtt_message_type msgType = ((mqtt_message_type)pdata[0] >> 4) & 0x0F;
switch(msgType) { switch(msgType) {
case MQTT_MSG_TYPE_CONNACK: case MQTT_MSG_TYPE_CONNACK:
os_printf("CONNACK recieved...\n"); os_printf("CONNACK recieved...\n");
switch(pdata[3]) { switch(pdata[3]) {
case 0: case 0:
os_printf("Connection accepted.\n"); os_printf("Connection accepted.\n");
break; break;
case 1: case 1:
os_printf("Connection refused -- incorrect protocol version.\n"); os_printf("Connection refused -- incorrect protocol version.\n");
break; break;
case 2: case 2:
os_printf("Connection refused -- illegal identifier.\n"); os_printf("Connection refused -- illegal identifier.\n");
break; break;
case 3: case 3:
os_printf("Connection refused -- broker offline or not available.\n"); os_printf("Connection refused -- broker offline or not available.\n");
break; break;
case 4: case 4:
os_printf("Connection refused -- bad username or password.\n"); os_printf("Connection refused -- bad username or password.\n");
break; break;
case 5: case 5:
os_printf("Connection refused -- not authorized.\n"); os_printf("Connection refused -- not authorized.\n");
break; break;
default: default:
os_printf("Connection refused -- illegal CONNACK return code.\n"); os_printf("Connection refused -- illegal CONNACK return code.\n");
break; break;
} }
if(session->connack_cb != NULL) { if(session->connack_cb != NULL) {
session->connack_cb(pdata); session->connack_cb(pdata);
} }
break; break;
case MQTT_MSG_TYPE_PUBLISH: case MQTT_MSG_TYPE_PUBLISH:
os_printf("Application message from server: %s\n", &pdata[3]); // probably incorrect os_printf("Application message from server: %s\n", &pdata[3]); // probably incorrect
if(session->publish_cb != NULL) { if(session->publish_cb != NULL) {
session->publish_cb(pdata); session->publish_cb(pdata);
} }
break; break;
case MQTT_MSG_TYPE_SUBACK: case MQTT_MSG_TYPE_SUBACK:
os_printf("Subscription acknowledged\n"); os_printf("Subscription acknowledged\n");
break; break;
case MQTT_MSG_TYPE_UNSUBACK: case MQTT_MSG_TYPE_UNSUBACK:
os_printf("Unsubscription acknowledged\n"); os_printf("Unsubscription acknowledged\n");
break; break;
case MQTT_MSG_TYPE_PINGRESP: case MQTT_MSG_TYPE_PINGRESP:
os_printf("Pong!\n"); os_printf("Pong!\n");
break; break;
// all remaining cases listed to avoid warnings // all remaining cases listed to avoid warnings
case MQTT_MSG_TYPE_CONNECT: case MQTT_MSG_TYPE_CONNECT:
case MQTT_MSG_TYPE_PUBACK: case MQTT_MSG_TYPE_PUBACK:
case MQTT_MSG_TYPE_PUBREC: case MQTT_MSG_TYPE_PUBREC:
case MQTT_MSG_TYPE_PUBREL: case MQTT_MSG_TYPE_PUBREL:
case MQTT_MSG_TYPE_PUBCOMP: case MQTT_MSG_TYPE_PUBCOMP:
case MQTT_MSG_TYPE_SUBSCRIBE: case MQTT_MSG_TYPE_SUBSCRIBE:
case MQTT_MSG_TYPE_UNSUBSCRIBE: case MQTT_MSG_TYPE_UNSUBSCRIBE:
case MQTT_MSG_TYPE_PINGREQ: case MQTT_MSG_TYPE_PINGREQ:
case MQTT_MSG_TYPE_DISCONNECT: case MQTT_MSG_TYPE_DISCONNECT:
default: default:
if(msgType == MQTT_MSG_TYPE_DISCONNECT) { if(msgType == MQTT_MSG_TYPE_DISCONNECT) {
os_printf("MQTT Disconnect packet\n"); os_printf("MQTT Disconnect packet\n");
} }
return; return;
break; break;
} }
} }
void ICACHE_FLASH_ATTR connected_callback(void *arg) { void ICACHE_FLASH_ATTR connected_callback(void *arg) {
struct espconn *pConn = arg; struct espconn *pConn = arg;
mqtt_session_t *pSession = pConn->reverse; mqtt_session_t *pSession = pConn->reverse;
#ifdef DEBUG #ifdef DEBUG
os_printf("Connected callback\n"); os_printf("Connected callback\n");
#endif #endif
espconn_regist_recvcb(pConn, (espconn_recv_callback)data_recv_callback); espconn_regist_recvcb(pConn, (espconn_recv_callback)data_recv_callback);
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; pSession->validConnection = 1;
} }
void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) { void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) {
os_printf("Reconnected?\n"); os_printf("Reconnected?\n");
os_printf("Error code: %d\n", err); os_printf("Error code: %d\n", err);
} }
void ICACHE_FLASH_ATTR disconnected_callback(void *arg) { void ICACHE_FLASH_ATTR disconnected_callback(void *arg) {
os_printf("Disconnected\n"); os_printf("Disconnected\n");
os_timer_disarm(&pubTimer); os_timer_disarm(&pubTimer);
os_timer_disarm(&pingTimer); os_timer_disarm(&pingTimer);
} }
uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) { uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) {
os_timer_disarm(&waitForWifiTimer); os_timer_disarm(&waitForWifiTimer);
struct ip_info ipConfig; struct ip_info ipConfig;
mqtt_session_t *session = arg; mqtt_session_t *session = arg;
wifi_get_ip_info(STATION_IF, &ipConfig);
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipConfig.ip.addr != 0) {
LOCAL struct espconn conn;
LOCAL struct _esp_tcp tcp_s;
conn.reverse = arg;
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) {
LOCAL struct espconn conn;
LOCAL struct _esp_tcp tcp_s;
conn.reverse = arg;
#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); #ifdef DEBUG
os_printf("About to connect\n"); os_printf("About to register callbacks\n");
//make the connection #endif
if(espconn_connect(&conn) == 0) { // register callbacks
os_printf("Connection successful\n"); espconn_regist_connectcb(&conn, (espconn_connect_callback)connected_callback);
espconn_regist_reconcb(&conn, (espconn_reconnect_callback)reconnected_callback);
espconn_regist_disconcb(&conn, (espconn_connect_callback)disconnected_callback);
#ifdef DEBUG
os_printf("About to connect\n");
#endif
//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 { } else {
os_printf("Connection error\n"); // set timer to try again
os_timer_setfn(&waitForWifiTimer, (os_timer_func_t *)tcpConnect, session);
os_timer_arm(&waitForWifiTimer, 1000, 0);
return 2;
} }
session->activeConnection = &conn;
#ifdef DEBUG
os_printf("About to return from TCP connect\n");
#endif
return 0; return 0;
}
else {
// set timer to try again
os_timer_setfn(&waitForWifiTimer, (os_timer_func_t *)tcpConnect, session);
os_timer_arm(&waitForWifiTimer, 1000, 0);
return 2;
}
return 0;
} }
uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength) { 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
uint8_t numBytes = 1; uint8_t numBytes = 1;
do { do {
encodedByte[numBytes] = trueLength % 128; encodedByte[numBytes] = trueLength % 128;
trueLength /= 128; trueLength /= 128;
if(trueLength > 0) { if(trueLength > 0) {
encodedByte[numBytes] |= 128; encodedByte[numBytes] |= 128;
} }
numBytes++; numBytes++;
} while(trueLength > 0); } while(trueLength > 0);
encodedByte[0] = numBytes - 1; encodedByte[0] = numBytes - 1;
return encodedByte; return encodedByte;
} }
void ICACHE_FLASH_ATTR pingAlive(void *arg) { void ICACHE_FLASH_ATTR pingAlive(void *arg) {
mqtt_session_t *pSession = (mqtt_session_t *)arg; mqtt_session_t *pSession = (mqtt_session_t *)arg;
mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ);
} }
uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType) { uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType) {
if(session->validConnection == 1) { if(session->validConnection == 1) {
os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called
#ifdef DEBUG #ifdef DEBUG
os_printf("Entering mqttSend!\n"); os_printf("Entering mqttSend!\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: { case MQTT_MSG_TYPE_PUBLISH: {
// prepare for publish // prepare for publish
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5); 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 pPacket->fixedHeader[0] = (MQTT_MSG_TYPE_PUBLISH << 4) & 0xF0; // clear lower 4 bits, we don't need DUP, QOS or RETAIN
// variable header // variable header
// A PUBLISH Packet MUST NOT contain a Packet Identifier if its QoS value is set to 0 [MQTT-2.3.1-5]. // 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_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); pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
os_memset(pPacket->varHeader, 0, 1); os_memset(pPacket->varHeader, 0, 1);
os_memcpy(pPacket->varHeader + 1, &session->topic_name_len, 1); os_memcpy(pPacket->varHeader + 1, &session->topic_name_len, 1);
os_memcpy(pPacket->varHeader + 2, session->topic_name, session->topic_name_len); os_memcpy(pPacket->varHeader + 2, session->topic_name, session->topic_name_len);
//payload //payload
pPacket->payload_len = len; pPacket->payload_len = len;
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len); pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
os_memcpy(pPacket->payload, data, pPacket->payload_len); os_memcpy(pPacket->payload, data, pPacket->payload_len);
// calculate remaining length for fixed header // calculate remaining length for fixed header
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);
os_printf("Packet length: %d\n", pPacket->length); os_printf("Packet length: %d\n", pPacket->length);
// 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_SUBSCRIBE: case MQTT_MSG_TYPE_SUBSCRIBE:
case MQTT_MSG_TYPE_UNSUBSCRIBE: case MQTT_MSG_TYPE_UNSUBSCRIBE:
// prepare for subscribe // prepare for subscribe
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5); pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 5);
pPacket->fixedHeader[0] = ((msgType << 4) & 0xF0) | 0x02; pPacket->fixedHeader[0] = ((msgType << 4) & 0xF0) | 0x02;
pPacket->varHeader_len = 2; pPacket->varHeader_len = 2;
pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len); pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->varHeader_len);
os_memset(pPacket->varHeader, 0, 2); // set packet ID to 0 os_memset(pPacket->varHeader, 0, 2); // set packet ID to 0
uint8_t extraByte = (msgType == MQTT_MSG_TYPE_SUBSCRIBE) ? 3 : 2; uint8_t extraByte = (msgType == MQTT_MSG_TYPE_SUBSCRIBE) ? 3 : 2;
pPacket->payload_len = session->topic_name_len + extraByte; pPacket->payload_len = session->topic_name_len + extraByte;
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len); pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * pPacket->payload_len);
pPacket->payload[1] = session->topic_name_len % 0xFF; pPacket->payload[1] = session->topic_name_len % 0xFF;
pPacket->payload[0] = 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 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; if(msgType == MQTT_MSG_TYPE_SUBSCRIBE) pPacket->payload[session->topic_name_len+2] = 0;
// calculate remaining length for fixed header // calculate remaining length for fixed header
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);
os_printf("Packet length: %d\n", pPacket->length); os_printf("Packet length: %d\n", pPacket->length);
// 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_PINGREQ: case MQTT_MSG_TYPE_PINGREQ:
case MQTT_MSG_TYPE_DISCONNECT: case MQTT_MSG_TYPE_DISCONNECT:
// PINGREQ has no varHeader or payload, it's just two bytes // PINGREQ has no varHeader or payload, it's just two bytes
// 0xC0 0x00 // 0xC0 0x00
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 2); pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 2);
pPacket->fixedHeader[0] = (msgType << 4) & 0xF0; // bottom nibble must be clear pPacket->fixedHeader[0] = (msgType << 4) & 0xF0; // bottom nibble must be clear
pPacket->fixedHeader[1] = 0; // remaining length is zero pPacket->fixedHeader[1] = 0; // remaining length is zero
pPacket->fixedHeader_len = 2; pPacket->fixedHeader_len = 2;
pPacket->length = pPacket->fixedHeader_len; pPacket->length = pPacket->fixedHeader_len;
// In order to avoid undefined behaviour, we must allocate // In order to avoid undefined behaviour, we must allocate
// something to varHeader and payload, as they get passed // something to varHeader and payload, as they get passed
// to free() at the end of this function // to free() at the end of this function
pPacket->varHeader = (uint8_t *)os_zalloc(1); pPacket->varHeader = (uint8_t *)os_zalloc(1);
pPacket->payload = (uint8_t *)os_zalloc(1); pPacket->payload = (uint8_t *)os_zalloc(1);
// copy the fixedHeader to fullPacket, and we're done! // copy the fixedHeader to fullPacket, and we're done!
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);
break; break;
default: default:
// something has gone wrong // something has gone wrong
os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType); os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType);
return -1; return -1;
}
#ifdef DEBUG
os_printf("About to send MQTT command type: %d...\n", (uint8_t)msgType);
#endif
espconn_send(session->activeConnection, fullPacket, pPacket->length);
os_free(fullPacket);
os_free(pPacket->fixedHeader);
os_free(pPacket->varHeader);
os_free(pPacket->payload);
// set up keepalive timer
if(msgType != MQTT_MSG_TYPE_DISCONNECT) {
os_timer_setfn(&MQTT_KeepAliveTimer, (os_timer_func_t *)pingAlive, session);
os_timer_arm(&MQTT_KeepAliveTimer, 30000, 0);
}
} else {
os_printf("No wifi! Narf!\n");
} }
#ifdef DEBUG return 0;
os_printf("About to send MQTT command type: %d...\n", (uint8_t)msgType);
#endif
espconn_send(session->activeConnection, fullPacket, pPacket->length);
os_free(fullPacket);
os_free(pPacket->fixedHeader);
os_free(pPacket->varHeader);
os_free(pPacket->payload);
// set up keepalive timer
if(msgType != MQTT_MSG_TYPE_DISCONNECT) {
os_timer_setfn(&MQTT_KeepAliveTimer, (os_timer_func_t *)pingAlive, session);
os_timer_arm(&MQTT_KeepAliveTimer, 30000, 0);
}
} else {
os_printf("No wifi! Narf!\n");
}
return 0;
} }

87
mqtt.h
View file

@ -20,7 +20,7 @@
#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 */ #define DEBUG 1 /**< This define enables or disables serial debug output in most places */
/** /**
* @typedef * @typedef
@ -28,22 +28,21 @@
* *
* 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 mqttSend() to construct the correct packet type. * 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 mqttSend() 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, MQTT_MSG_TYPE_CONNACK = 2,
MQTT_MSG_TYPE_CONNACK = 2, MQTT_MSG_TYPE_PUBLISH = 3,
MQTT_MSG_TYPE_PUBLISH = 3, MQTT_MSG_TYPE_PUBACK = 4,
MQTT_MSG_TYPE_PUBACK = 4, MQTT_MSG_TYPE_PUBREC = 5,
MQTT_MSG_TYPE_PUBREC = 5, MQTT_MSG_TYPE_PUBREL = 6,
MQTT_MSG_TYPE_PUBREL = 6, MQTT_MSG_TYPE_PUBCOMP = 7,
MQTT_MSG_TYPE_PUBCOMP = 7, MQTT_MSG_TYPE_SUBSCRIBE = 8,
MQTT_MSG_TYPE_SUBSCRIBE = 8, MQTT_MSG_TYPE_SUBACK = 9,
MQTT_MSG_TYPE_SUBACK = 9, MQTT_MSG_TYPE_UNSUBSCRIBE = 10,
MQTT_MSG_TYPE_UNSUBSCRIBE = 10, MQTT_MSG_TYPE_UNSUBACK = 11,
MQTT_MSG_TYPE_UNSUBACK = 11, MQTT_MSG_TYPE_PINGREQ = 12,
MQTT_MSG_TYPE_PINGREQ = 12, MQTT_MSG_TYPE_PINGRESP = 13,
MQTT_MSG_TYPE_PINGRESP = 13, MQTT_MSG_TYPE_DISCONNECT = 14
MQTT_MSG_TYPE_DISCONNECT = 14
} mqtt_message_type; } mqtt_message_type;
/** /**
@ -53,14 +52,14 @@ typedef enum mqtt_message_enum
* 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. * 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; /**< The pointer to the fixed header bytes */ uint8_t *fixedHeader; /**< The pointer to the fixed header bytes */
uint32_t fixedHeader_len; /**< The length of the fixed header */ uint32_t fixedHeader_len; /**< The length of the fixed header */
uint8_t *varHeader; /**< The pointer to the variable header bytes */ uint8_t *varHeader; /**< The pointer to the variable header bytes */
uint32_t varHeader_len; /**< The length of the variable header */ uint32_t varHeader_len; /**< The length of the variable header */
uint8_t *payload; /**< The pointer to the payload bytes */ uint8_t *payload; /**< The pointer to the payload bytes */
uint32_t payload_len; /**< The length of the payload */ uint32_t payload_len; /**< The length of the payload */
uint32_t length; /**< The full length of the packet */ uint32_t length; /**< The full length of the packet */
mqtt_message_type msgType; /**< What message type this packet contains */ mqtt_message_type msgType; /**< What message type this packet contains */
} mqtt_packet_t; } mqtt_packet_t;
/** /**
@ -68,24 +67,24 @@ typedef struct {
* Structure that contains all the information to establish and maintain a TCP-based MQTT connection to the broker * 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]; /**< An array containing the four bytes of the IP address of the broker */ uint8_t ip[4]; /**< An array containing the four bytes of the IP address of the broker */
uint32_t port; /**< The port the broker is listening on */ uint32_t port; /**< The port the broker is listening on */
uint32_t localPort; /**< The local port returned by the ESP8266 function espconn_port() */ uint32_t localPort; /**< The local port returned by the ESP8266 function espconn_port() */
uint8_t *client_id; /**< Pointer to the client ID string */ uint8_t *client_id; /**< Pointer to the client ID string */
uint32_t client_id_len; /**< Length of the client ID string */ uint32_t client_id_len; /**< Length of the client ID string */
uint8_t *topic_name; /**< Pointer to the topic name string */ uint8_t *topic_name; /**< Pointer to the topic name string */
uint32_t topic_name_len; /**< Length of the topic name string */ uint32_t topic_name_len; /**< Length of the topic name string */
uint8_t qos_level; /**< QOS level of the MQTT connection (always 0, not currently used) */ uint8_t qos_level; /**< QOS level of the MQTT connection (always 0, not currently used) */
uint8_t *username; /**< Pointer to the username string, for brokers which require authentication */ uint8_t *username; /**< Pointer to the username string, for brokers which require authentication */
uint32_t username_len; /**< The length of the username string */ uint32_t username_len; /**< The length of the username string */
uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */ uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */
uint32_t password_len; /**< The length of the password string */ uint32_t password_len; /**< The length of the password string */
char validConnection; /**< Boolean value which indicates whether or not the TCP connection is established, set in tcpConnect() */ char validConnection; /**< Boolean value which indicates whether or not the TCP connection is established, set in tcpConnect() */
struct espconn *activeConnection; /**< A pointer to the espconn structure containing details of the TCP connection */ struct espconn *activeConnection; /**< A pointer to the espconn structure containing details of the TCP connection */
void *userData; /**< Used to pass data to the PUBLISH function */ void *userData; /**< Used to pass data to the PUBLISH function */
// Add pointers to user callback functions // Add pointers to user callback functions
void (*publish_cb)(void *arg); /**< Pointer to user callback function for publish */ void (*publish_cb)(void *arg); /**< Pointer to user callback function for publish */
void (*connack_cb)(void *arg); /**< Pointer to user callback function for connack */ void (*connack_cb)(void *arg); /**< Pointer to user callback function for connack */
} mqtt_session_t; } mqtt_session_t;
/** /**
@ -135,7 +134,7 @@ uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength);
* @param session a pointer to the active mqtt_session_t * @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 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 len the length of the above data
* @param msgType the type of message to be send, one of the mqtt_message_type * @param msgType the type of message to be sent, one of the mqtt_message_type
* @return -1 in case of error, 0 otherwise * @return -1 in case of error, 0 otherwise
*/ */
uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType); uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType);

180
onewire.c
View file

@ -12,98 +12,98 @@
#define OWBUS BIT5 /**< This define determines which pin is used */ #define OWBUS BIT5 /**< This define determines which pin is used */
sint8 ICACHE_FLASH_ATTR reset(void) { sint8 ICACHE_FLASH_ATTR reset(void) {
uint32_t time; uint32_t time;
// reset the ow line, check for presence? // reset the ow line, check for presence?
time = system_get_time() + 500; time = system_get_time() + 500;
gpio_output_set(0, OWBUS, OWBUS, 0); // pull GPIO4 low gpio_output_set(0, OWBUS, OWBUS, 0); // pull GPIO4 low
while(system_get_time() < time); // delay 500uS while(system_get_time() < time); // delay 500uS
gpio_output_set(0, 0, 0, OWBUS); // let go of GPIO4 gpio_output_set(0, 0, 0, OWBUS); // let go of GPIO4
time = system_get_time() + 60; time = system_get_time() + 60;
while(system_get_time() < time); while(system_get_time() < time);
uint8_t presence = (uint8_t)(gpio_input_get() >> 5) & 0x1; uint8_t presence = (uint8_t)(gpio_input_get() >> 5) & 0x1;
// give a 480uS pause so the next onewire event doesn't get trampled // give a 480uS pause so the next onewire event doesn't get trampled
time = system_get_time() + 480; time = system_get_time() + 480;
while(system_get_time() < time); while(system_get_time() < time);
if(!presence) { if(!presence) {
return 1; return 1;
} else { } else {
return -1; return -1;
} }
} }
void ICACHE_FLASH_ATTR transact(oneWire_t *owDev, ds18b20_cmds cmd) { void ICACHE_FLASH_ATTR transact(oneWire_t *owDev, ds18b20_cmds cmd) {
uint32_t time; uint32_t time;
uint8_t sendBit; uint8_t sendBit;
uint8_t inBit = 0x00; uint8_t inBit = 0x00;
uint8_t inByte = 0x00; uint8_t inByte = 0x00;
switch(cmd) { switch(cmd) {
os_printf("\nOnewire command: %d\n", cmd); os_printf("\nOnewire command: %d\n", cmd);
case SKIP_ROM: case SKIP_ROM:
case CONVERT_T: case CONVERT_T:
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
sendBit = (cmd >> i) & 0x1; sendBit = (cmd >> i) & 0x1;
//os_printf("\nThe bit is: %d \t i is %d\n", sendBit, i); //os_printf("\nThe bit is: %d \t i is %d\n", sendBit, i);
if(sendBit == 1) { if(sendBit == 1) {
//os_printf("\nWe are in sendBit == 1\n"); //os_printf("\nWe are in sendBit == 1\n");
time = system_get_time() + 10; time = system_get_time() + 10;
gpio_output_set(0, OWBUS, OWBUS, 0); // pull low gpio_output_set(0, OWBUS, OWBUS, 0); // pull low
while(system_get_time() < time); while(system_get_time() < time);
gpio_output_set(0, 0, 0, OWBUS); // let go gpio_output_set(0, 0, 0, OWBUS); // let go
time = system_get_time() + 50; time = system_get_time() + 50;
while(system_get_time() < time); while(system_get_time() < time);
} else { } else {
//os_printf("\nWe are in the sendBit else\n"); //os_printf("\nWe are in the sendBit else\n");
time = system_get_time() + 100; time = system_get_time() + 100;
gpio_output_set(0, OWBUS, OWBUS, 0); //pull low gpio_output_set(0, OWBUS, OWBUS, 0); //pull low
while(system_get_time() < time); while(system_get_time() < time);
gpio_output_set(0, 0, 0, OWBUS); // let go gpio_output_set(0, 0, 0, OWBUS); // let go
time = system_get_time() + 10; time = system_get_time() + 10;
while(system_get_time() < time); while(system_get_time() < time);
} }
} }
break; break;
case SCRATCH_READ: case SCRATCH_READ:
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
sendBit = (cmd >> i) & 0x1; sendBit = (cmd >> i) & 0x1;
if(sendBit == 1) { if(sendBit == 1) {
//os_printf("\nWe are in sendBit == 1\n"); //os_printf("\nWe are in sendBit == 1\n");
time = system_get_time() + 10; time = system_get_time() + 10;
gpio_output_set(0, OWBUS, OWBUS, 0); // pull low gpio_output_set(0, OWBUS, OWBUS, 0); // pull low
while(system_get_time() < time); while(system_get_time() < time);
gpio_output_set(0, 0, 0, OWBUS); // let go gpio_output_set(0, 0, 0, OWBUS); // let go
time = system_get_time() + 50; time = system_get_time() + 50;
while(system_get_time() < time); while(system_get_time() < time);
} else { } else {
//os_printf("\nWe are in the sendBit else\n"); //os_printf("\nWe are in the sendBit else\n");
time = system_get_time() + 100; time = system_get_time() + 100;
gpio_output_set(0, OWBUS, OWBUS, 0); //pull low gpio_output_set(0, OWBUS, OWBUS, 0); //pull low
while(system_get_time() < time); while(system_get_time() < time);
gpio_output_set(0, 0, 0, OWBUS); // let go gpio_output_set(0, 0, 0, OWBUS); // let go
time = system_get_time() + 10; time = system_get_time() + 10;
while(system_get_time() < time); while(system_get_time() < time);
} }
} }
// now read the scratchpad // now read the scratchpad
for(uint8_t i = 0; i < 2; i++) { for(uint8_t i = 0; i < 2; i++) {
for(uint8_t j = 0; j < 8; j++) { for(uint8_t j = 0; j < 8; j++) {
time = system_get_time() + 8; time = system_get_time() + 8;
gpio_output_set(0, OWBUS, OWBUS, 0); gpio_output_set(0, OWBUS, OWBUS, 0);
while(system_get_time() < time); while(system_get_time() < time);
gpio_output_set(0, 0, 0, OWBUS); gpio_output_set(0, 0, 0, OWBUS);
time = system_get_time() + 15; time = system_get_time() + 15;
while(system_get_time() < time); while(system_get_time() < time);
inBit = (uint8_t)(gpio_input_get() >> 5) & 0x01; inBit = (uint8_t)(gpio_input_get() >> 5) & 0x01;
inByte |= inBit << j; inByte |= inBit << j;
time = system_get_time() + 45; time = system_get_time() + 45;
while(system_get_time() < time); while(system_get_time() < time);
} }
owDev->scratchpad[i] = inByte; owDev->scratchpad[i] = inByte;
inByte = 0; // clear inByte inByte = 0; // clear inByte
} }
break; break;
default: default:
os_printf("\nIncorrect command\n"); os_printf("\nIncorrect command\n");
break; break;
} }
} }

View file

@ -16,9 +16,9 @@
* Structure that holds all the information about onewire connections, including the 64-bit ROM address for each device and some buffer memory to read out the scratchpad * Structure that holds all the information about onewire connections, including the 64-bit ROM address for each device and some buffer memory to read out the scratchpad
*/ */
typedef struct { typedef struct {
uint8_t address[8]; uint8_t address[8];
uint8_t scratchpad[9]; uint8_t scratchpad[9];
float temperature; float temperature;
} oneWire_t; } oneWire_t;
/** /**
@ -26,16 +26,16 @@ typedef struct {
* This enum simply gives easy to read names to all the various one-wire commands that the DS18B20 can accept * This enum simply gives easy to read names to all the various one-wire commands that the DS18B20 can accept
*/ */
typedef enum { typedef enum {
READ_ROM = 0x33, READ_ROM = 0x33,
MATCH_ROM = 0x55, MATCH_ROM = 0x55,
SEARCH_ROM = 0xF0, SEARCH_ROM = 0xF0,
ALARM_SEARCH = 0xEC, ALARM_SEARCH = 0xEC,
SKIP_ROM = 0xCC, SKIP_ROM = 0xCC,
CONVERT_T = 0x44, CONVERT_T = 0x44,
SCRATCH_READ = 0xBE, SCRATCH_READ = 0xBE,
SCRATCH_WRITE = 0x4E, SCRATCH_WRITE = 0x4E,
SCRATCH_COPY = 0x48, SCRATCH_COPY = 0x48,
E2_RECALL = 0xB8 E2_RECALL = 0xB8
} ds18b20_cmds; } ds18b20_cmds;
/** /**