From 8acff6e8805266fd6b2f2dbf964302aa99b09e3b Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Wed, 27 Feb 2019 02:28:00 -0500 Subject: [PATCH 1/9] Updated to v0.3.1 Renamed mqtt_send to mqttSend to better follow my usual naming convention. Made a few other small changes, including disabling the debug macro by default. Just uncomment to add it again. This is the version that will be used with the first release of Part 3 of the SDK tutorials on hackaday.io. Signed-off-by: A.M. Rowsell --- Doxyfile | 2 +- main.c | 36 ++++++++++++++++++++++-------------- mqtt.c | 9 ++++++--- mqtt.h | 6 +++--- 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/Doxyfile b/Doxyfile index 122a79d..60e8104 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = mqtt-esp8266 # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = v0.2 +PROJECT_NUMBER = v0.3.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/main.c b/main.c index 9d96351..8454ade 100644 --- a/main.c +++ b/main.c @@ -16,7 +16,7 @@ os_timer_t pubTimer; LOCAL void ICACHE_FLASH_ATTR con(void *arg) { os_printf("Entered con!\n"); mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT); + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT); os_timer_disarm(&pingTimer); os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); @@ -30,7 +30,7 @@ LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg) { char *dataStr = os_zalloc(20 * sizeof(char)); intToStr(*data, dataStr, 4); int32_t dataLen = os_strlen(dataStr); - mqtt_send(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH); + 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); @@ -44,16 +44,18 @@ LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg) { ftoa(*data, dataStr, 2); int32_t dataLen = os_strlen(dataStr); os_printf("Encoded string: %s\tString length: %d\n", dataStr, dataLen); - mqtt_send(pSession, (uint8_t *)dataStr, dataLen, MQTT_MSG_TYPE_PUBLISH); + 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) { +#ifdef DEBUG os_printf("Entered ping!\n"); +#endif mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); os_timer_disarm(&pingTimer); os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); os_timer_arm(&pingTimer, 1000, 0); @@ -62,15 +64,16 @@ LOCAL void ICACHE_FLASH_ATTR ping(void *arg) { LOCAL void ICACHE_FLASH_ATTR sub(void *arg) { os_printf("Entered sub!\n"); mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_SUBSCRIBE); + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_SUBSCRIBE); } LOCAL void ICACHE_FLASH_ATTR discon(void *arg) { os_printf("Entered discon!\n"); mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT); + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT); os_timer_disarm(&pingTimer); + os_timer_disarm(&pubTimer); } LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { @@ -79,6 +82,7 @@ LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { oneWire_t *pDS18 = &DS18; uint16_t temp = 0; sint32 time = 0; + pDS18->temperature = 0; reset(); transact(pDS18, SKIP_ROM); @@ -94,38 +98,41 @@ LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { pSession->userData = (void *)&pDS18->temperature; os_printf("\nTemperature is: %d.%02d\n", (int)pDS18->temperature, (int)(pDS18->temperature * 100) % 100); pubfloat(pSession); // publish the temperature - + //discon(pSession); + return; } void ICACHE_FLASH_ATTR user_init() { - //uint8_t wifiStatus; LOCAL mqtt_session_t globalSession; LOCAL mqtt_session_t *pGlobalSession = &globalSession; char ssid[32] = "yourwifissid"; char passkey[64] = "yourwifipass"; struct station_config stationConf; - gpio_init(); // init gpio so we can use the LED - uart_div_modify(0, UART_CLK_FREQ / 115200); // set UART to 115200 + + gpio_init(); // init gpio so we can use the LED & onewire bus + 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 stationConf.bssid_set = 0; os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct os_memcpy(&stationConf.password, passkey, 64); wifi_set_opmode_current(0x01); //station mode wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well + // prepare the TCP/MQTT connection stuff // Adafruit IO is at 52.5.238.97 + // 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 uint8_t ioUser_len = 11; static const char ioKey[32] = { }; // use strtoarr.py to generate these 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 uint8_t ioTopic_len = 27; - /* static const char ioTopic[37] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x73, 0x2f, 0x62, 0x65, 0x64, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x62, 0x65, 0x64, 0x72, 0x6f, 0x6f, 0x6d, 0x74, 0x65, 0x6d, 0x70 }; */ - /* static const uint8_t ioTopic_len = 37; */ + static const uint8_t ioTopic_len = 27; static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 static const uint8_t clientID_len = 5; pGlobalSession->port = 1883; // mqtt port static const char adafruitIO_ip[4] = {52, 5, 238, 97}; + + // copy all the above info into our mqtt_session_t os_memcpy(pGlobalSession->ip, adafruitIO_ip, 4); pGlobalSession->username_len = ioUser_len; pGlobalSession->username = os_zalloc(sizeof(uint8_t) * pGlobalSession->username_len); @@ -139,7 +146,8 @@ void ICACHE_FLASH_ATTR user_init() { pGlobalSession->client_id_len = clientID_len; pGlobalSession->client_id = os_zalloc(sizeof(uint8_t) * pGlobalSession->client_id_len); os_memcpy(pGlobalSession->client_id, clientID, pGlobalSession->client_id_len); - + + // set up all the timers to connect and log data os_timer_setfn(&tcpTimer, (os_timer_func_t *)tcpConnect, pGlobalSession); os_timer_arm(&tcpTimer, 12000, 0); os_timer_setfn(&pingTimer, (os_timer_func_t *)con, pGlobalSession); diff --git a/mqtt.c b/mqtt.c index 7192c25..f757afc 100644 --- a/mqtt.c +++ b/mqtt.c @@ -89,7 +89,10 @@ void ftoa(float n, char *res, int afterpoint) } void ICACHE_FLASH_ATTR data_sent_callback(void *arg) { +#ifdef DEBUG os_printf("Data sent!\n"); +#endif + return; } void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) { @@ -266,14 +269,14 @@ uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength) { void ICACHE_FLASH_ATTR pingAlive(void *arg) { mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); } -uint8_t ICACHE_FLASH_ATTR mqtt_send(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) { os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called #ifdef DEBUG - os_printf("Entering mqtt_send!\n"); + os_printf("Entering mqttSend!\n"); #endif LOCAL mqtt_packet_t packet; LOCAL mqtt_packet_t *pPacket = &packet; diff --git a/mqtt.h b/mqtt.h index 22ef4ed..866ca4f 100644 --- a/mqtt.h +++ b/mqtt.h @@ -20,13 +20,13 @@ #include "espconn.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 * 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. + * 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 { @@ -138,4 +138,4 @@ uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength); * @param msgType the type of message to be send, one of the mqtt_message_type * @return -1 in case of error, 0 otherwise */ -uint8_t ICACHE_FLASH_ATTR mqtt_send(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); From 70973a0b14e8ff5f8808495a6ed267db2449a0a3 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Wed, 27 Feb 2019 02:31:42 -0500 Subject: [PATCH 2/9] Added DHT prototypes. Added the beginning of the DHT code which will likely be used in part 4 of the tutorial series. Signed-off-by: A.M. Rowsell --- dht.c | 27 +++++++++++++++++++++++++++ dht.h | 4 ++++ 2 files changed, 31 insertions(+) create mode 100644 dht.c create mode 100644 dht.h diff --git a/dht.c b/dht.c new file mode 100644 index 0000000..34cdea7 --- /dev/null +++ b/dht.c @@ -0,0 +1,27 @@ +#include +#include "user_interface.h" +#include "os_type.h" +#include "osapi.h" +#include "gpio.h" +#include "dht.h" + +#define DHTBus BIT4 + +LOCAL uint8_t ICACHE_FLASH_ATTR getBitNum(uint32_t bit) { + uint32_t localBit = bit; + for(uint8_t i = 0; i <= 16; i++) { + localBit >>= i; + if(bit & 0x01) { + return i; + } + } + return -1; // if we reached this spot we received a bad number +} +void ICACHE_FLASH_ATTR setupDHT(void) { + gpio_output_set(0, DHTBus, 0, DHTBus); // set up DHTBus as active low output + ETS_GPIO_INTR_ATTACH(func, NULL); +} + +void ICACHE_FLASH_ATTR getDHTData(void) { + +} diff --git a/dht.h b/dht.h new file mode 100644 index 0000000..794fc8b --- /dev/null +++ b/dht.h @@ -0,0 +1,4 @@ +#include "os_type.h" + +void ICACHE_FLASH_ATTR setupDHT(uint8_t pin); +void ICACHE_FLASH_ATTR getDHTData(uint8_t pin); From d0b019edff51b691e383b7431fadf555e662feb5 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Wed, 27 Feb 2019 02:40:10 -0500 Subject: [PATCH 3/9] Updated to v0.3.2 --- Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doxyfile b/Doxyfile index 122a79d..7067fc8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = mqtt-esp8266 # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = v0.2 +PROJECT_NUMBER = v0.3.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 7c5dfae57b61977f60e5aec641e58851eaf13277 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Mon, 4 Mar 2019 12:58:17 -0500 Subject: [PATCH 4/9] Updated formatting with astyle -A14 -S Signed-off-by: A.M. Rowsell --- README.md | 2 + dht.c | 20 +- main.c | 236 +++++++++-------- mqtt.c | 738 +++++++++++++++++++++++++++--------------------------- mqtt.h | 87 ++++--- onewire.c | 180 ++++++------- onewire.h | 26 +- 7 files changed, 651 insertions(+), 638 deletions(-) diff --git a/README.md b/README.md index 1f2f07d..a84351c 100644 --- a/README.md +++ b/README.md @@ -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. 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! diff --git a/dht.c b/dht.c index 34cdea7..937d526 100644 --- a/dht.c +++ b/dht.c @@ -8,20 +8,20 @@ #define DHTBus BIT4 LOCAL uint8_t ICACHE_FLASH_ATTR getBitNum(uint32_t bit) { - uint32_t localBit = bit; - for(uint8_t i = 0; i <= 16; i++) { - localBit >>= i; - if(bit & 0x01) { - return i; + uint32_t localBit = bit; + for(uint8_t i = 0; i <= 16; i++) { + localBit >>= i; + if(bit & 0x01) { + 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) { - gpio_output_set(0, DHTBus, 0, DHTBus); // set up DHTBus as active low output - ETS_GPIO_INTR_ATTACH(func, NULL); + gpio_output_set(0, DHTBus, 0, DHTBus); // set up DHTBus as active low output + ETS_GPIO_INTR_ATTACH(func, NULL); } void ICACHE_FLASH_ATTR getDHTData(void) { - + } diff --git a/main.c b/main.c index 8454ade..719ef25 100644 --- a/main.c +++ b/main.c @@ -14,144 +14,160 @@ os_timer_t pingTimer; os_timer_t pubTimer; LOCAL void ICACHE_FLASH_ATTR con(void *arg) { - os_printf("Entered con!\n"); - mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT); +#ifdef DEBUG + os_printf("Entered con!\n"); +#endif + mqtt_session_t *pSession = (mqtt_session_t *)arg; + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT); - os_timer_disarm(&pingTimer); - os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); - 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 pubuint(void *arg) { - os_printf("Entered pubuint!\n"); - mqtt_session_t *pSession = (mqtt_session_t *)arg; - uint8_t *data = (uint8_t *)(pSession->userData); - char *dataStr = os_zalloc(20 * sizeof(char)); - intToStr(*data, dataStr, 4); - int32_t dataLen = os_strlen(dataStr); - 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); +#ifdef DEBUG + os_printf("Entered pubuint!\n"); +#endif + mqtt_session_t *pSession = (mqtt_session_t *)arg; + uint8_t *data = (uint8_t *)(pSession->userData); + char *dataStr = os_zalloc(20 * sizeof(char)); + intToStr(*data, dataStr, 4); + int32_t dataLen = os_strlen(dataStr); + 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 pubfloat(void *arg) { - os_printf("Entered pubfloat!\n"); - mqtt_session_t *pSession = (mqtt_session_t *)arg; - float *data = (float *)(pSession->userData); - char *dataStr = os_zalloc(20 * sizeof(char)); - ftoa(*data, dataStr, 2); - int32_t dataLen = os_strlen(dataStr); - os_printf("Encoded string: %s\tString length: %d\n", dataStr, dataLen); - 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); +#ifdef DEBUG + os_printf("Entered pubfloat!\n"); +#endif + mqtt_session_t *pSession = (mqtt_session_t *)arg; + float *data = (float *)(pSession->userData); + char *dataStr = os_zalloc(20 * sizeof(char)); + ftoa(*data, dataStr, 2); + int32_t dataLen = os_strlen(dataStr); +#ifdef DEBUG + os_printf("Encoded string: %s\tString length: %d\n", dataStr, dataLen); +#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) { #ifdef DEBUG - os_printf("Entered ping!\n"); + os_printf("Entered ping!\n"); #endif - mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); - os_timer_disarm(&pingTimer); - os_timer_setfn(&pingTimer, (os_timer_func_t *)ping, arg); - os_timer_arm(&pingTimer, 1000, 0); + mqtt_session_t *pSession = (mqtt_session_t *)arg; + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); + 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 sub(void *arg) { - os_printf("Entered sub!\n"); - mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_SUBSCRIBE); +#ifdef DEBUG + os_printf("Entered sub!\n"); +#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) { - os_printf("Entered discon!\n"); - mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT); - os_timer_disarm(&pingTimer); - os_timer_disarm(&pubTimer); +#ifdef DEBUG + os_printf("Entered discon!\n"); +#endif + mqtt_session_t *pSession = (mqtt_session_t *)arg; + mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_DISCONNECT); + os_timer_disarm(&pingTimer); + os_timer_disarm(&pubTimer); } LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { - mqtt_session_t *pSession = (mqtt_session_t *)arg; - oneWire_t DS18; - oneWire_t *pDS18 = &DS18; - uint16_t temp = 0; - sint32 time = 0; + mqtt_session_t *pSession = (mqtt_session_t *)arg; + oneWire_t DS18; + oneWire_t *pDS18 = &DS18; + uint16_t temp = 0; + sint32 time = 0; - pDS18->temperature = 0; - reset(); - transact(pDS18, SKIP_ROM); - transact(pDS18, CONVERT_T); - time = system_get_time() + 750000; - while(system_get_time() < time); - reset(); - transact(pDS18, SKIP_ROM); - transact(pDS18, SCRATCH_READ); - //os_printf("\nReceived onewire data: %x %x\n", pDS18->scratchpad[0], pDS18->scratchpad[1]); - temp = ((uint16_t)pDS18->scratchpad[1] << 8) | pDS18->scratchpad[0]; - pDS18->temperature += (temp >> 4) + ((temp & 0x0F) * 0.0625); - pSession->userData = (void *)&pDS18->temperature; - os_printf("\nTemperature is: %d.%02d\n", (int)pDS18->temperature, (int)(pDS18->temperature * 100) % 100); - pubfloat(pSession); // publish the temperature - //discon(pSession); - return; + pDS18->temperature = 0; + reset(); + transact(pDS18, SKIP_ROM); + transact(pDS18, CONVERT_T); + time = system_get_time() + 750000; + while(system_get_time() < time); + reset(); + transact(pDS18, SKIP_ROM); + transact(pDS18, SCRATCH_READ); +#ifdef DEBUG + os_printf("\nReceived onewire data: %x %x\n", pDS18->scratchpad[0], pDS18->scratchpad[1]); +#endif + temp = ((uint16_t)pDS18->scratchpad[1] << 8) | pDS18->scratchpad[0]; + pDS18->temperature += (temp >> 4) + ((temp & 0x0F) * 0.0625); + pSession->userData = (void *)&pDS18->temperature; +#ifdef DEBUG + 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() { - LOCAL mqtt_session_t globalSession; - LOCAL mqtt_session_t *pGlobalSession = &globalSession; - char ssid[32] = "yourwifissid"; - char passkey[64] = "yourwifipass"; - struct station_config stationConf; + LOCAL mqtt_session_t globalSession; + LOCAL mqtt_session_t *pGlobalSession = &globalSession; + char ssid[32] = "yourwifissid"; + char passkey[64] = "yourwifipass"; + struct station_config stationConf; - gpio_init(); // init gpio so we can use the LED & onewire bus - 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 - stationConf.bssid_set = 0; - os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct - os_memcpy(&stationConf.password, passkey, 64); - wifi_set_opmode_current(0x01); //station mode - wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well + gpio_init(); // init gpio so we can use the LED & onewire bus + 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 + stationConf.bssid_set = 0; + os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct + os_memcpy(&stationConf.password, passkey, 64); + wifi_set_opmode_current(0x01); //station mode + wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well - // prepare the TCP/MQTT connection stuff - // Adafruit IO is at 52.5.238.97 - // 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 uint8_t ioUser_len = 11; - static const char ioKey[32] = { }; // use strtoarr.py to generate these - 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 uint8_t ioTopic_len = 27; - static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 - static const uint8_t clientID_len = 5; - pGlobalSession->port = 1883; // mqtt port - static const char adafruitIO_ip[4] = {52, 5, 238, 97}; + // prepare the TCP/MQTT connection stuff + // Adafruit IO is at 52.5.238.97 + // 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 uint8_t ioUser_len = 11; + static const char ioKey[32] = { }; // use strtoarr.py to generate these + 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 uint8_t ioTopic_len = 27; + static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 + static const uint8_t clientID_len = 5; + pGlobalSession->port = 1883; // mqtt port + static const char adafruitIO_ip[4] = {52, 5, 238, 97}; - // copy all the above info into our mqtt_session_t - os_memcpy(pGlobalSession->ip, adafruitIO_ip, 4); - pGlobalSession->username_len = ioUser_len; - pGlobalSession->username = os_zalloc(sizeof(uint8_t) * pGlobalSession->username_len); - os_memcpy(pGlobalSession->username, ioUser, pGlobalSession->username_len); - pGlobalSession->password_len = ioKey_len; - pGlobalSession->password = os_zalloc(sizeof(uint8_t) * pGlobalSession->password_len); - os_memcpy(pGlobalSession->password, ioKey, pGlobalSession->password_len); - pGlobalSession->topic_name_len = ioTopic_len; - pGlobalSession->topic_name = os_zalloc(sizeof(uint8_t) * pGlobalSession->topic_name_len); - os_memcpy(pGlobalSession->topic_name, ioTopic, pGlobalSession->topic_name_len); - pGlobalSession->client_id_len = clientID_len; - pGlobalSession->client_id = os_zalloc(sizeof(uint8_t) * pGlobalSession->client_id_len); - os_memcpy(pGlobalSession->client_id, clientID, pGlobalSession->client_id_len); + // copy all the above info into our mqtt_session_t + os_memcpy(pGlobalSession->ip, adafruitIO_ip, 4); + pGlobalSession->username_len = ioUser_len; + pGlobalSession->username = os_zalloc(sizeof(uint8_t) * pGlobalSession->username_len); + os_memcpy(pGlobalSession->username, ioUser, pGlobalSession->username_len); + pGlobalSession->password_len = ioKey_len; + pGlobalSession->password = os_zalloc(sizeof(uint8_t) * pGlobalSession->password_len); + os_memcpy(pGlobalSession->password, ioKey, pGlobalSession->password_len); + pGlobalSession->topic_name_len = ioTopic_len; + pGlobalSession->topic_name = os_zalloc(sizeof(uint8_t) * pGlobalSession->topic_name_len); + os_memcpy(pGlobalSession->topic_name, ioTopic, pGlobalSession->topic_name_len); + pGlobalSession->client_id_len = clientID_len; + pGlobalSession->client_id = os_zalloc(sizeof(uint8_t) * pGlobalSession->client_id_len); + os_memcpy(pGlobalSession->client_id, clientID, pGlobalSession->client_id_len); - // set up all the timers to connect and log data - os_timer_setfn(&tcpTimer, (os_timer_func_t *)tcpConnect, pGlobalSession); - os_timer_arm(&tcpTimer, 12000, 0); - os_timer_setfn(&pingTimer, (os_timer_func_t *)con, pGlobalSession); - os_timer_arm(&pingTimer, 16000, 0); - os_timer_setfn(&pubTimer, (os_timer_func_t *)dataLog, pGlobalSession); - os_timer_arm(&pubTimer, 20000, 1); + // set up all the timers to connect and log data + os_timer_setfn(&tcpTimer, (os_timer_func_t *)tcpConnect, pGlobalSession); + os_timer_arm(&tcpTimer, 12000, 0); + os_timer_setfn(&pingTimer, (os_timer_func_t *)con, pGlobalSession); + os_timer_arm(&pingTimer, 16000, 0); + os_timer_setfn(&pubTimer, (os_timer_func_t *)dataLog, pGlobalSession); + os_timer_arm(&pubTimer, 20000, 1); } diff --git a/mqtt.c b/mqtt.c index f757afc..57ac40b 100644 --- a/mqtt.c +++ b/mqtt.c @@ -25,423 +25,419 @@ */ static os_timer_t MQTT_KeepAliveTimer; -static os_timer_t waitForWifiTimer; +static os_timer_t waitForWifiTimer; -// reverses a string 'str' of length 'len' -void reverse(char *str, int len) -{ - int i=0, j=len-1, temp; - while (ireverse; - // deal with received data + struct espconn *pConn = arg; + mqtt_session_t *session = pConn->reverse; + // deal with received data #ifdef DEBUG - os_printf("Received data of length %d -- %s \r\n", len, pdata); - os_printf("Hex dump: "); - for(int i = 0; i < len; i++) { - os_printf("(%d): %x ", i, pdata[i]); - } - os_printf("\n"); + os_printf("Received data of length %d -- %s \r\n", len, pdata); + os_printf("Hex dump: "); + for(int i = 0; i < len; i++) { + os_printf("(%d): %x ", i, pdata[i]); + } + os_printf("\n"); #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); - } - 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; - - } + 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); + } + 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; + + } } void ICACHE_FLASH_ATTR connected_callback(void *arg) { - struct espconn *pConn = arg; - mqtt_session_t *pSession = pConn->reverse; + struct espconn *pConn = arg; + mqtt_session_t *pSession = pConn->reverse; #ifdef DEBUG - os_printf("Connected callback\n"); + os_printf("Connected callback\n"); #endif - espconn_regist_recvcb(pConn, (espconn_recv_callback)data_recv_callback); - espconn_regist_sentcb(pConn, (espconn_sent_callback)data_sent_callback); - // enable keepalive - espconn_set_opt(pConn, ESPCONN_KEEPALIVE); - pSession->validConnection = 1; + espconn_regist_recvcb(pConn, (espconn_recv_callback)data_recv_callback); + espconn_regist_sentcb(pConn, (espconn_sent_callback)data_sent_callback); + // enable keepalive + espconn_set_opt(pConn, ESPCONN_KEEPALIVE); + pSession->validConnection = 1; } void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) { - os_printf("Reconnected?\n"); - os_printf("Error code: %d\n", err); + os_printf("Reconnected?\n"); + os_printf("Error code: %d\n", err); } void ICACHE_FLASH_ATTR disconnected_callback(void *arg) { - os_printf("Disconnected\n"); - os_timer_disarm(&pubTimer); - os_timer_disarm(&pingTimer); + os_printf("Disconnected\n"); + os_timer_disarm(&pubTimer); + os_timer_disarm(&pingTimer); } uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) { - os_timer_disarm(&waitForWifiTimer); - struct ip_info ipConfig; - 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 + os_timer_disarm(&waitForWifiTimer); + struct ip_info ipConfig; + mqtt_session_t *session = arg; 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 - os_printf("about to set up TCP params\n"); + os_printf("Entered tcpConnect\n"); #endif - conn.proto.tcp = &tcp_s; - conn.type = ESPCONN_TCP; - conn.proto.tcp->local_port = espconn_port(); - conn.proto.tcp->remote_port = session->port; - conn.state = ESPCONN_NONE; - os_memcpy(conn.proto.tcp->remote_ip, session->ip, 4); - - os_printf("About to register callbacks\n"); - // register callbacks - 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); - os_printf("About to connect\n"); - //make the connection - if(espconn_connect(&conn) == 0) { - os_printf("Connection successful\n"); + wifi_get_ip_info(STATION_IF, &ipConfig); + // set up basic TCP connection parameters +#ifdef DEBUG + os_printf("about to set up TCP params\n"); +#endif + conn.proto.tcp = &tcp_s; + conn.type = ESPCONN_TCP; + conn.proto.tcp->local_port = espconn_port(); + conn.proto.tcp->remote_port = session->port; + conn.state = ESPCONN_NONE; + os_memcpy(conn.proto.tcp->remote_ip, session->ip, 4); +#ifdef DEBUG + os_printf("About to register callbacks\n"); +#endif + // register callbacks + 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 { - 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; - } - 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 *encodedByte = os_zalloc(sizeof(uint8_t) * 5); // can't be more than 5 bytes - uint8_t numBytes = 1; - do { - encodedByte[numBytes] = trueLength % 128; - trueLength /= 128; - if(trueLength > 0) { - encodedByte[numBytes] |= 128; - } - numBytes++; - } while(trueLength > 0); - encodedByte[0] = numBytes - 1; - - return encodedByte; + uint8_t *encodedByte = os_zalloc(sizeof(uint8_t) * 5); // can't be more than 5 bytes + uint8_t numBytes = 1; + do { + encodedByte[numBytes] = trueLength % 128; + trueLength /= 128; + if(trueLength > 0) { + encodedByte[numBytes] |= 128; + } + numBytes++; + } while(trueLength > 0); + encodedByte[0] = numBytes - 1; + + return encodedByte; } void ICACHE_FLASH_ATTR pingAlive(void *arg) { - mqtt_session_t *pSession = (mqtt_session_t *)arg; - mqttSend(pSession, NULL, 0, MQTT_MSG_TYPE_PINGREQ); + mqtt_session_t *pSession = (mqtt_session_t *)arg; + 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) { - if(session->validConnection == 1) { - os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called + if(session->validConnection == 1) { + os_timer_disarm(&MQTT_KeepAliveTimer); // disable timer if we are called #ifdef DEBUG - os_printf("Entering mqttSend!\n"); + os_printf("Entering mqttSend!\n"); #endif - LOCAL mqtt_packet_t packet; - LOCAL mqtt_packet_t *pPacket = &packet; - 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 + LOCAL mqtt_packet_t packet; + LOCAL mqtt_packet_t *pPacket = &packet; + 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 #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 - - // 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; + // 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); + + //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 + 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 - 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; + return 0; } diff --git a/mqtt.h b/mqtt.h index 866ca4f..f46a32e 100644 --- a/mqtt.h +++ b/mqtt.h @@ -20,7 +20,7 @@ #include "espconn.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 @@ -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. */ -typedef enum mqtt_message_enum -{ - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 +typedef enum mqtt_message_enum { + MQTT_MSG_TYPE_CONNECT = 1, + MQTT_MSG_TYPE_CONNACK = 2, + MQTT_MSG_TYPE_PUBLISH = 3, + MQTT_MSG_TYPE_PUBACK = 4, + MQTT_MSG_TYPE_PUBREC = 5, + MQTT_MSG_TYPE_PUBREL = 6, + MQTT_MSG_TYPE_PUBCOMP = 7, + MQTT_MSG_TYPE_SUBSCRIBE = 8, + MQTT_MSG_TYPE_SUBACK = 9, + MQTT_MSG_TYPE_UNSUBSCRIBE = 10, + MQTT_MSG_TYPE_UNSUBACK = 11, + MQTT_MSG_TYPE_PINGREQ = 12, + MQTT_MSG_TYPE_PINGRESP = 13, + MQTT_MSG_TYPE_DISCONNECT = 14 } 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. */ typedef struct { - uint8_t *fixedHeader; /**< The pointer to the fixed header bytes */ - uint32_t fixedHeader_len; /**< The length of the fixed header */ - uint8_t *varHeader; /**< The pointer to the variable header bytes */ - uint32_t varHeader_len; /**< The length of the variable header */ - uint8_t *payload; /**< The pointer to the payload bytes */ - uint32_t payload_len; /**< The length of the payload */ - uint32_t length; /**< The full length of the packet */ - mqtt_message_type msgType; /**< What message type this packet contains */ + uint8_t *fixedHeader; /**< The pointer to the fixed header bytes */ + uint32_t fixedHeader_len; /**< The length of the fixed header */ + uint8_t *varHeader; /**< The pointer to the variable header bytes */ + uint32_t varHeader_len; /**< The length of the variable header */ + uint8_t *payload; /**< The pointer to the payload bytes */ + uint32_t payload_len; /**< The length of the payload */ + uint32_t length; /**< The full length of the packet */ + mqtt_message_type msgType; /**< What message type this packet contains */ } 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 */ typedef struct { - 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 localPort; /**< The local port returned by the ESP8266 function espconn_port() */ - uint8_t *client_id; /**< Pointer to 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 */ - 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 *username; /**< Pointer to the username string, for brokers which require authentication */ - uint32_t username_len; /**< The length of the username string */ - uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */ - 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() */ - 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 */ - // Add pointers to user callback functions - void (*publish_cb)(void *arg); /**< Pointer to user callback function for publish */ - void (*connack_cb)(void *arg); /**< Pointer to user callback function for connack */ + 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 localPort; /**< The local port returned by the ESP8266 function espconn_port() */ + uint8_t *client_id; /**< Pointer to 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 */ + 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 *username; /**< Pointer to the username string, for brokers which require authentication */ + uint32_t username_len; /**< The length of the username string */ + uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */ + 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() */ + 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 */ + // Add pointers to user callback functions + void (*publish_cb)(void *arg); /**< Pointer to user callback function for publish */ + void (*connack_cb)(void *arg); /**< Pointer to user callback function for connack */ } 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 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 + * @param msgType the type of message to be sent, one of the mqtt_message_type * @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); diff --git a/onewire.c b/onewire.c index 23b399e..1bc3ef2 100644 --- a/onewire.c +++ b/onewire.c @@ -12,98 +12,98 @@ #define OWBUS BIT5 /**< This define determines which pin is used */ sint8 ICACHE_FLASH_ATTR reset(void) { - uint32_t time; - // reset the ow line, check for presence? - time = system_get_time() + 500; - gpio_output_set(0, OWBUS, OWBUS, 0); // pull GPIO4 low - while(system_get_time() < time); // delay 500uS - gpio_output_set(0, 0, 0, OWBUS); // let go of GPIO4 - time = system_get_time() + 60; - while(system_get_time() < time); - uint8_t presence = (uint8_t)(gpio_input_get() >> 5) & 0x1; - // give a 480uS pause so the next onewire event doesn't get trampled - time = system_get_time() + 480; - while(system_get_time() < time); + uint32_t time; + // reset the ow line, check for presence? + time = system_get_time() + 500; + gpio_output_set(0, OWBUS, OWBUS, 0); // pull GPIO4 low + while(system_get_time() < time); // delay 500uS + gpio_output_set(0, 0, 0, OWBUS); // let go of GPIO4 + time = system_get_time() + 60; + while(system_get_time() < time); + uint8_t presence = (uint8_t)(gpio_input_get() >> 5) & 0x1; + // give a 480uS pause so the next onewire event doesn't get trampled + time = system_get_time() + 480; + while(system_get_time() < time); - if(!presence) { - return 1; - } else { - return -1; - } + if(!presence) { + return 1; + } else { + return -1; + } } void ICACHE_FLASH_ATTR transact(oneWire_t *owDev, ds18b20_cmds cmd) { - uint32_t time; - uint8_t sendBit; - uint8_t inBit = 0x00; - uint8_t inByte = 0x00; - switch(cmd) { - os_printf("\nOnewire command: %d\n", cmd); - case SKIP_ROM: - case CONVERT_T: - for(uint8_t i = 0; i < 8; i++) { - sendBit = (cmd >> i) & 0x1; - //os_printf("\nThe bit is: %d \t i is %d\n", sendBit, i); - if(sendBit == 1) { - //os_printf("\nWe are in sendBit == 1\n"); - time = system_get_time() + 10; - gpio_output_set(0, OWBUS, OWBUS, 0); // pull low - while(system_get_time() < time); - gpio_output_set(0, 0, 0, OWBUS); // let go - time = system_get_time() + 50; - while(system_get_time() < time); - } else { - //os_printf("\nWe are in the sendBit else\n"); - time = system_get_time() + 100; - gpio_output_set(0, OWBUS, OWBUS, 0); //pull low - while(system_get_time() < time); - gpio_output_set(0, 0, 0, OWBUS); // let go - time = system_get_time() + 10; - while(system_get_time() < time); - } - } - break; - case SCRATCH_READ: - for(uint8_t i = 0; i < 8; i++) { - sendBit = (cmd >> i) & 0x1; - if(sendBit == 1) { - //os_printf("\nWe are in sendBit == 1\n"); - time = system_get_time() + 10; - gpio_output_set(0, OWBUS, OWBUS, 0); // pull low - while(system_get_time() < time); - gpio_output_set(0, 0, 0, OWBUS); // let go - time = system_get_time() + 50; - while(system_get_time() < time); - } else { - //os_printf("\nWe are in the sendBit else\n"); - time = system_get_time() + 100; - gpio_output_set(0, OWBUS, OWBUS, 0); //pull low - while(system_get_time() < time); - gpio_output_set(0, 0, 0, OWBUS); // let go - time = system_get_time() + 10; - while(system_get_time() < time); - } - } - // now read the scratchpad - for(uint8_t i = 0; i < 2; i++) { - for(uint8_t j = 0; j < 8; j++) { - time = system_get_time() + 8; - gpio_output_set(0, OWBUS, OWBUS, 0); - while(system_get_time() < time); - gpio_output_set(0, 0, 0, OWBUS); - time = system_get_time() + 15; - while(system_get_time() < time); - inBit = (uint8_t)(gpio_input_get() >> 5) & 0x01; - inByte |= inBit << j; - time = system_get_time() + 45; - while(system_get_time() < time); - } - owDev->scratchpad[i] = inByte; - inByte = 0; // clear inByte - } - break; - default: - os_printf("\nIncorrect command\n"); - break; - } + uint32_t time; + uint8_t sendBit; + uint8_t inBit = 0x00; + uint8_t inByte = 0x00; + switch(cmd) { + os_printf("\nOnewire command: %d\n", cmd); + case SKIP_ROM: + case CONVERT_T: + for(uint8_t i = 0; i < 8; i++) { + sendBit = (cmd >> i) & 0x1; + //os_printf("\nThe bit is: %d \t i is %d\n", sendBit, i); + if(sendBit == 1) { + //os_printf("\nWe are in sendBit == 1\n"); + time = system_get_time() + 10; + gpio_output_set(0, OWBUS, OWBUS, 0); // pull low + while(system_get_time() < time); + gpio_output_set(0, 0, 0, OWBUS); // let go + time = system_get_time() + 50; + while(system_get_time() < time); + } else { + //os_printf("\nWe are in the sendBit else\n"); + time = system_get_time() + 100; + gpio_output_set(0, OWBUS, OWBUS, 0); //pull low + while(system_get_time() < time); + gpio_output_set(0, 0, 0, OWBUS); // let go + time = system_get_time() + 10; + while(system_get_time() < time); + } + } + break; + case SCRATCH_READ: + for(uint8_t i = 0; i < 8; i++) { + sendBit = (cmd >> i) & 0x1; + if(sendBit == 1) { + //os_printf("\nWe are in sendBit == 1\n"); + time = system_get_time() + 10; + gpio_output_set(0, OWBUS, OWBUS, 0); // pull low + while(system_get_time() < time); + gpio_output_set(0, 0, 0, OWBUS); // let go + time = system_get_time() + 50; + while(system_get_time() < time); + } else { + //os_printf("\nWe are in the sendBit else\n"); + time = system_get_time() + 100; + gpio_output_set(0, OWBUS, OWBUS, 0); //pull low + while(system_get_time() < time); + gpio_output_set(0, 0, 0, OWBUS); // let go + time = system_get_time() + 10; + while(system_get_time() < time); + } + } + // now read the scratchpad + for(uint8_t i = 0; i < 2; i++) { + for(uint8_t j = 0; j < 8; j++) { + time = system_get_time() + 8; + gpio_output_set(0, OWBUS, OWBUS, 0); + while(system_get_time() < time); + gpio_output_set(0, 0, 0, OWBUS); + time = system_get_time() + 15; + while(system_get_time() < time); + inBit = (uint8_t)(gpio_input_get() >> 5) & 0x01; + inByte |= inBit << j; + time = system_get_time() + 45; + while(system_get_time() < time); + } + owDev->scratchpad[i] = inByte; + inByte = 0; // clear inByte + } + break; + default: + os_printf("\nIncorrect command\n"); + break; + } } diff --git a/onewire.h b/onewire.h index 0da4c8d..8115d0e 100644 --- a/onewire.h +++ b/onewire.h @@ -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 */ typedef struct { - uint8_t address[8]; - uint8_t scratchpad[9]; - float temperature; + uint8_t address[8]; + uint8_t scratchpad[9]; + float temperature; } 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 */ typedef enum { - READ_ROM = 0x33, - MATCH_ROM = 0x55, - SEARCH_ROM = 0xF0, - ALARM_SEARCH = 0xEC, - SKIP_ROM = 0xCC, - CONVERT_T = 0x44, - SCRATCH_READ = 0xBE, - SCRATCH_WRITE = 0x4E, - SCRATCH_COPY = 0x48, - E2_RECALL = 0xB8 + READ_ROM = 0x33, + MATCH_ROM = 0x55, + SEARCH_ROM = 0xF0, + ALARM_SEARCH = 0xEC, + SKIP_ROM = 0xCC, + CONVERT_T = 0x44, + SCRATCH_READ = 0xBE, + SCRATCH_WRITE = 0x4E, + SCRATCH_COPY = 0x48, + E2_RECALL = 0xB8 } ds18b20_cmds; /** From dc724a2c9649234c4c202b6b821f71f9d76b99dd Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Sat, 6 Apr 2019 09:52:45 -0400 Subject: [PATCH 5/9] Merged updates from dev branch into master Signed-off-by: A.M. Rowsell --- main.c | 11 ++++++----- strtoarr.py | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/main.c b/main.c index 719ef25..5a17640 100644 --- a/main.c +++ b/main.c @@ -121,8 +121,8 @@ LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { void ICACHE_FLASH_ATTR user_init() { LOCAL mqtt_session_t globalSession; LOCAL mqtt_session_t *pGlobalSession = &globalSession; - char ssid[32] = "yourwifissid"; char passkey[64] = "yourwifipass"; + char ssid[32] = "yourwifissid"; struct station_config stationConf; gpio_init(); // init gpio so we can use the LED & onewire bus @@ -137,14 +137,15 @@ void ICACHE_FLASH_ATTR user_init() { // prepare the TCP/MQTT connection stuff // Adafruit IO is at 52.5.238.97 // 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 uint8_t ioUser_len = 11; - static const char ioKey[32] = { }; // use strtoarr.py to generate these + static const char ioUser[ioUser_len] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52 }; // MrAureliusR 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 ioKey[ioKey_len] = { }; static const uint8_t ioTopic_len = 27; - static const char clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 + static const char ioTopic[ioTopic_len] = { 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 clientID_len = 5; + static const char clientID[clientID_len] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 + pGlobalSession->port = 1883; // mqtt port static const char adafruitIO_ip[4] = {52, 5, 238, 97}; diff --git a/strtoarr.py b/strtoarr.py index 5f3198d..3a5cf45 100755 --- a/strtoarr.py +++ b/strtoarr.py @@ -21,7 +21,8 @@ import os inString = str(sys.argv[1]); -print("static const char {0}[{1}] = {{ ".format(sys.argv[2], len(inString)), end='') +print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) +print("static const char {0}[{0}_len] = {{ ".format(sys.argv[2], len(inString)), end='') for letter in inString[:-1]: p = ord(letter) print("{0:#x}, ".format(p), end='') @@ -29,4 +30,4 @@ for letter in inString[:-1]: p = ord(inString[-1]) print("{0:#x} ".format(int(p)), end='') print("}; // " + inString) -print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) + From 0aac8d5b66052274f67c7d2f21d4cea55dae502c Mon Sep 17 00:00:00 2001 From: AMRowsell Date: Sun, 7 Apr 2019 14:14:27 +0000 Subject: [PATCH 6/9] Revert "Merged updates from dev branch into master" This reverts commit dc724a2c9649234c4c202b6b821f71f9d76b99dd --- main.c | 11 +++++------ strtoarr.py | 5 ++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/main.c b/main.c index 5a17640..719ef25 100644 --- a/main.c +++ b/main.c @@ -121,8 +121,8 @@ LOCAL void ICACHE_FLASH_ATTR dataLog(void *arg) { void ICACHE_FLASH_ATTR user_init() { LOCAL mqtt_session_t globalSession; LOCAL mqtt_session_t *pGlobalSession = &globalSession; - char passkey[64] = "yourwifipass"; char ssid[32] = "yourwifissid"; + char passkey[64] = "yourwifipass"; struct station_config stationConf; gpio_init(); // init gpio so we can use the LED & onewire bus @@ -137,15 +137,14 @@ void ICACHE_FLASH_ATTR user_init() { // prepare the TCP/MQTT connection stuff // Adafruit IO is at 52.5.238.97 // 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 uint8_t ioUser_len = 11; - static const char ioUser[ioUser_len] = { 0x4d, 0x72, 0x41, 0x75, 0x72, 0x65, 0x6c, 0x69, 0x75, 0x73, 0x52 }; // MrAureliusR + static const char ioKey[32] = { }; // use strtoarr.py to generate these static const uint8_t ioKey_len = 32; - static const char ioKey[ioKey_len] = { }; + 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 char ioTopic[ioTopic_len] = { 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 clientID[5] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 static const uint8_t clientID_len = 5; - static const char clientID[clientID_len] = { 0x46, 0x52, 0x5a, 0x4e, 0x30 }; // FRZN0 - pGlobalSession->port = 1883; // mqtt port static const char adafruitIO_ip[4] = {52, 5, 238, 97}; diff --git a/strtoarr.py b/strtoarr.py index 3a5cf45..5f3198d 100755 --- a/strtoarr.py +++ b/strtoarr.py @@ -21,8 +21,7 @@ import os inString = str(sys.argv[1]); -print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) -print("static const char {0}[{0}_len] = {{ ".format(sys.argv[2], len(inString)), end='') +print("static const char {0}[{1}] = {{ ".format(sys.argv[2], len(inString)), end='') for letter in inString[:-1]: p = ord(letter) print("{0:#x}, ".format(p), end='') @@ -30,4 +29,4 @@ for letter in inString[:-1]: p = ord(inString[-1]) print("{0:#x} ".format(int(p)), end='') print("}; // " + inString) - +print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) From 59b1b748fff7b3f7fe5036efbe40d5701346e693 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Thu, 11 Apr 2019 17:08:12 -0400 Subject: [PATCH 7/9] Fixed compile-time warnings --- .gitignore | 3 ++- main.c | 12 ++++++------ main.h | 12 ++++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 2e52dc7..f2d5e28 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ mqtt .\#* pcap/ docs/latex/ -docs/man/ \ No newline at end of file +docs/man/ +.vscode \ No newline at end of file diff --git a/main.c b/main.c index 719ef25..776762d 100644 --- a/main.c +++ b/main.c @@ -13,7 +13,7 @@ os_timer_t tcpTimer; os_timer_t pingTimer; os_timer_t pubTimer; -LOCAL void ICACHE_FLASH_ATTR con(void *arg) { +void ICACHE_FLASH_ATTR con(void *arg) { #ifdef DEBUG os_printf("Entered con!\n"); #endif @@ -25,7 +25,7 @@ LOCAL void ICACHE_FLASH_ATTR con(void *arg) { os_timer_arm(&pingTimer, 1000, 0); } -LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg) { +void ICACHE_FLASH_ATTR pubuint(void *arg) { #ifdef DEBUG os_printf("Entered pubuint!\n"); #endif @@ -40,7 +40,7 @@ LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg) { os_timer_arm(&pingTimer, 1000, 0); } -LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg) { +void ICACHE_FLASH_ATTR pubfloat(void *arg) { #ifdef DEBUG os_printf("Entered pubfloat!\n"); #endif @@ -58,7 +58,7 @@ LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg) { os_timer_arm(&pingTimer, 1000, 0); } -LOCAL void ICACHE_FLASH_ATTR ping(void *arg) { +void ICACHE_FLASH_ATTR ping(void *arg) { #ifdef DEBUG os_printf("Entered ping!\n"); #endif @@ -69,7 +69,7 @@ LOCAL void ICACHE_FLASH_ATTR ping(void *arg) { os_timer_arm(&pingTimer, 1000, 0); } -LOCAL void ICACHE_FLASH_ATTR sub(void *arg) { +void ICACHE_FLASH_ATTR sub(void *arg) { #ifdef DEBUG os_printf("Entered sub!\n"); #endif @@ -78,7 +78,7 @@ LOCAL void ICACHE_FLASH_ATTR sub(void *arg) { } -LOCAL void ICACHE_FLASH_ATTR discon(void *arg) { +void ICACHE_FLASH_ATTR discon(void *arg) { #ifdef DEBUG os_printf("Entered discon!\n"); #endif diff --git a/main.h b/main.h index b37edbe..8b1d1eb 100644 --- a/main.h +++ b/main.h @@ -8,11 +8,11 @@ void reverse(char *str, int len); int intToStr(int x, char str[], int d); void ftoa(float n, char *res, int afterpoint); -LOCAL void ICACHE_FLASH_ATTR con(void *arg); -LOCAL void ICACHE_FLASH_ATTR pubuint(void *arg); -LOCAL void ICACHE_FLASH_ATTR pubfloat(void *arg); -LOCAL void ICACHE_FLASH_ATTR sub(void *arg); -LOCAL void ICACHE_FLASH_ATTR ping(void *arg); -LOCAL void ICACHE_FLASH_ATTR discon(void *arg); +void ICACHE_FLASH_ATTR con(void *arg); +void ICACHE_FLASH_ATTR pubuint(void *arg); +void ICACHE_FLASH_ATTR pubfloat(void *arg); +void ICACHE_FLASH_ATTR sub(void *arg); +void ICACHE_FLASH_ATTR ping(void *arg); +void ICACHE_FLASH_ATTR discon(void *arg); void ICACHE_FLASH_ATTR user_init(); From 54ec66b3453ffe858e7ec56285c8c527fa223e2d Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Mon, 15 Apr 2019 23:40:34 -0400 Subject: [PATCH 8/9] Cleaned up strtoarr.py --- strtoarr.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/strtoarr.py b/strtoarr.py index 5f3198d..b5f0163 100755 --- a/strtoarr.py +++ b/strtoarr.py @@ -3,7 +3,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/. -#!/usr/bin/python3 + ## # @file # @brief File to create string arrays @@ -19,7 +19,7 @@ import sys import os -inString = str(sys.argv[1]); +inString = str(sys.argv[1]) print("static const char {0}[{1}] = {{ ".format(sys.argv[2], len(inString)), end='') for letter in inString[:-1]: @@ -27,6 +27,5 @@ for letter in inString[:-1]: print("{0:#x}, ".format(p), end='') p = ord(inString[-1]) -print("{0:#x} ".format(int(p)), end='') -print("}; // " + inString) -print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) +print("{0:#x} ".format(int(p)) + "}; // " + inString) +print("static const uint8_t {0}_len = {1};".format(sys.argv[2], len(inString))) \ No newline at end of file From a84326db7fe673e0cd8a9564eaba2db1bb73a4b5 Mon Sep 17 00:00:00 2001 From: "A.M. Rowsell" Date: Mon, 6 May 2024 08:02:52 -0400 Subject: [PATCH 9/9] 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