From a84326db7fe673e0cd8a9564eaba2db1bb73a4b5 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Mon, 6 May 2024 08:02:52 -0400 Subject: [PATCH] Re-formatted code and made some small changes to behaviour. At some point this repo might get updated to MQTT v5. I have to carefully read the standard and see what has changed. --- mqtt.c | 382 ++++++++++++++++++++++++++-------------------------- strtoarr.py | 0 2 files changed, 194 insertions(+), 188 deletions(-) mode change 100755 => 100644 strtoarr.py diff --git a/mqtt.c b/mqtt.c index 57ac40b..c7da508 100644 --- a/mqtt.c +++ b/mqtt.c @@ -104,66 +104,66 @@ void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short #endif mqtt_message_type msgType = ((mqtt_message_type)pdata[0] >> 4) & 0x0F; switch(msgType) { - case MQTT_MSG_TYPE_CONNACK: - os_printf("CONNACK recieved...\n"); - switch(pdata[3]) { - case 0: - os_printf("Connection accepted.\n"); - break; - case 1: - os_printf("Connection refused -- incorrect protocol version.\n"); - break; - case 2: - os_printf("Connection refused -- illegal identifier.\n"); - break; - case 3: - os_printf("Connection refused -- broker offline or not available.\n"); - break; - case 4: - os_printf("Connection refused -- bad username or password.\n"); - break; - case 5: - os_printf("Connection refused -- not authorized.\n"); - break; - default: - os_printf("Connection refused -- illegal CONNACK return code.\n"); - break; - } - if(session->connack_cb != NULL) { - session->connack_cb(pdata); - } + case MQTT_MSG_TYPE_CONNACK: + os_printf("CONNACK recieved...\n"); + switch(pdata[3]) { + case 0: + os_printf("Connection accepted.\n"); break; - case MQTT_MSG_TYPE_PUBLISH: - os_printf("Application message from server: %s\n", &pdata[3]); // probably incorrect - if(session->publish_cb != NULL) { - session->publish_cb(pdata); - } + case 1: + os_printf("Connection refused -- incorrect protocol version.\n"); break; - case MQTT_MSG_TYPE_SUBACK: - os_printf("Subscription acknowledged\n"); + case 2: + os_printf("Connection refused -- illegal identifier.\n"); break; - case MQTT_MSG_TYPE_UNSUBACK: - os_printf("Unsubscription acknowledged\n"); + case 3: + os_printf("Connection refused -- broker offline or not available.\n"); break; - case MQTT_MSG_TYPE_PINGRESP: - os_printf("Pong!\n"); + case 4: + os_printf("Connection refused -- bad username or password.\n"); + break; + case 5: + os_printf("Connection refused -- not authorized.\n"); break; - // all remaining cases listed to avoid warnings - case MQTT_MSG_TYPE_CONNECT: - case MQTT_MSG_TYPE_PUBACK: - case MQTT_MSG_TYPE_PUBREC: - case MQTT_MSG_TYPE_PUBREL: - case MQTT_MSG_TYPE_PUBCOMP: - case MQTT_MSG_TYPE_SUBSCRIBE: - case MQTT_MSG_TYPE_UNSUBSCRIBE: - case MQTT_MSG_TYPE_PINGREQ: - case MQTT_MSG_TYPE_DISCONNECT: default: - if(msgType == MQTT_MSG_TYPE_DISCONNECT) { - os_printf("MQTT Disconnect packet\n"); - } - return; + os_printf("Connection refused -- illegal CONNACK return code.\n"); break; + } + if(session->connack_cb != NULL) { + session->connack_cb(pdata); + } + break; + case MQTT_MSG_TYPE_PUBLISH: + os_printf("Application message from server: %s\n", &pdata[3]); // probably incorrect + if(session->publish_cb != NULL) { + session->publish_cb(pdata); + } + break; + case MQTT_MSG_TYPE_SUBACK: + os_printf("Subscription acknowledged\n"); + break; + case MQTT_MSG_TYPE_UNSUBACK: + os_printf("Unsubscription acknowledged\n"); + break; + case MQTT_MSG_TYPE_PINGRESP: + os_printf("Pong!\n"); + break; + // all remaining cases listed to avoid warnings + case MQTT_MSG_TYPE_CONNECT: + case MQTT_MSG_TYPE_PUBACK: + case MQTT_MSG_TYPE_PUBREC: + case MQTT_MSG_TYPE_PUBREL: + case MQTT_MSG_TYPE_PUBCOMP: + case MQTT_MSG_TYPE_SUBSCRIBE: + case MQTT_MSG_TYPE_UNSUBSCRIBE: + case MQTT_MSG_TYPE_PINGREQ: + case MQTT_MSG_TYPE_DISCONNECT: + default: + if(msgType == MQTT_MSG_TYPE_DISCONNECT) { + os_printf("MQTT Disconnect packet\n"); + } + return; + break; } } @@ -188,8 +188,9 @@ void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) { void ICACHE_FLASH_ATTR disconnected_callback(void *arg) { os_printf("Disconnected\n"); - os_timer_disarm(&pubTimer); - os_timer_disarm(&pingTimer); + /* These timers should be disarmed by the userspace code */ + /* os_timer_disarm(&pubTimer); */ + /* os_timer_disarm(&pingTimer); */ } uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) { @@ -279,149 +280,148 @@ uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint3 uint8_t *fullPacket; uint8_t *remaining_len_encoded; switch(msgType) { - 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 - 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 - // prepare variable header - pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 10); // 10 bytes for connect - os_memcpy(pPacket->varHeader, varDefaults, 10); // copy defaults - pPacket->varHeader_len = 10; - // prepare payload - 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 - pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * maxPayloadLength); - // copy client id to payload: 2 bytes for size, then client id. - // insert a 0 - os_memset(pPacket->payload + offset, 0, 1); // MSB is always 0 - offset += 1; - os_memcpy(pPacket->payload + offset, &session->client_id_len, 1); // LSB is length of string - offset += 1; - os_memcpy(pPacket->payload + offset, session->client_id, session->client_id_len); // and copy string - offset += session->client_id_len; - // copy username to payload: same as client id, 2 bytes for size, then username - // insert a 0 - os_memset(pPacket->payload + offset, 0, 1); - offset += 1; - os_memcpy(pPacket->payload + offset, &session->username_len, 1); - offset += 1; - os_memcpy(pPacket->payload + offset, session->username, session->username_len); - offset += session->username_len; - // Password: same as username and client id, 2 bytes for size, then password - // insert a 0 - os_memset(pPacket->payload + offset, 0, 1); - offset += 1; - os_memcpy(pPacket->payload + offset, &session->password_len, 1); - offset += 1; - os_memcpy(pPacket->payload + offset, session->password, session->password_len); - offset += session->password_len; - pPacket->payload_len = offset; // the length of the payload is the same as our offset + 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 + 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 + // prepare variable header + pPacket->varHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 10); // 10 bytes for connect + os_memcpy(pPacket->varHeader, varDefaults, 10); // copy defaults + pPacket->varHeader_len = 10; + // prepare payload + 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 + pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * maxPayloadLength); + // copy client id to payload: 2 bytes for size, then client id. + // insert a 0 + os_memset(pPacket->payload + offset, 0, 1); // MSB is always 0 + offset += 1; + os_memcpy(pPacket->payload + offset, &session->client_id_len, 1); // LSB is length of string + offset += 1; + os_memcpy(pPacket->payload + offset, session->client_id, session->client_id_len); // and copy string + offset += session->client_id_len; + // copy username to payload: same as client id, 2 bytes for size, then username + // insert a 0 + os_memset(pPacket->payload + offset, 0, 1); + offset += 1; + os_memcpy(pPacket->payload + offset, &session->username_len, 1); + offset += 1; + os_memcpy(pPacket->payload + offset, session->username, session->username_len); + offset += session->username_len; + // Password: same as username and client id, 2 bytes for size, then password + // insert a 0 + os_memset(pPacket->payload + offset, 0, 1); + offset += 1; + os_memcpy(pPacket->payload + offset, &session->password_len, 1); + offset += 1; + os_memcpy(pPacket->payload + offset, session->password, session->password_len); + offset += session->password_len; + pPacket->payload_len = offset; // the length of the payload is the same as our offset #ifdef DEBUG - os_printf("Total offset: %d\n", offset); + os_printf("Total offset: %d\n", offset); #endif - // 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 - // 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)); - 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); + // 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 + // 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)); + 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); #ifdef DEBUG - os_printf("Packet length: %d\n", pPacket->length); + os_printf("Packet length: %d\n", pPacket->length); #endif - // 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_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 + // 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_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); + // 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; + //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 - 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; - 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); - // 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_DISCONNECT: + case MQTT_MSG_TYPE_PINGREQ: + // PINGREQ and DISCONNECT have no varHeader or payload, it's just two bytes + 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: - 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; + // something has gone wrong + os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType); + return -1; } #ifdef DEBUG os_printf("About to send MQTT command type: %d...\n", (uint8_t)msgType); @@ -435,6 +435,12 @@ uint8_t ICACHE_FLASH_ATTR mqttSend(mqtt_session_t *session, uint8_t *data, uint3 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 { + /* If we send a disconnect packet, we must close the connection ourselves, + per MQTT standard 3.14.4 */ + espconn_disconnect(session->activeConnection); + os_timer_disarm(&MQTT_KeepAliveTimer); // ensure the keepalive timer is disarmed + return 0; } } else { os_printf("No wifi! Narf!\n"); diff --git a/strtoarr.py b/strtoarr.py old mode 100755 new mode 100644