From 15e72f825cd734fb6b1d5d22f52454bb3601b042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Grome=C5=A1?= Date: Fri, 29 Jun 2018 10:30:40 +0200 Subject: [PATCH] Replaced internal Arduino Strings with cstrings --- src/Module.cpp | 6 +- src/Module.h | 2 +- src/TypeDef.h | 82 +++---- src/modules/ESP8266.cpp | 478 +++++++++++++++++++++++++--------------- src/modules/ESP8266.h | 26 +-- 5 files changed, 361 insertions(+), 233 deletions(-) diff --git a/src/Module.cpp b/src/Module.cpp index 4e559e8f..4ff5cf79 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -11,10 +11,8 @@ Module::Module(int cs, int tx, int rx, int int0, int int1) { } uint8_t Module::init(uint8_t interface, uint8_t gpio) { - #ifdef DEBUG - Serial.begin(9600); - Serial.println(); - #endif + DEBUG_BEGIN(9600); + DEBUG_PRINTLN(); switch(interface) { case USE_SPI: diff --git a/src/Module.h b/src/Module.h index 802d430a..8f773734 100644 --- a/src/Module.h +++ b/src/Module.h @@ -17,7 +17,7 @@ class Module { SoftwareSerial* ModuleSerial; uint32_t baudrate = 9600; - String AtLineFeed = "\r\n"; + const char* AtLineFeed = "\r\n"; uint8_t init(uint8_t interface, uint8_t gpio); diff --git a/src/TypeDef.h b/src/TypeDef.h index 0ab4e569..42059540 100644 --- a/src/TypeDef.h +++ b/src/TypeDef.h @@ -9,68 +9,74 @@ //#define DEBUG -#ifdef DEBUG +/*#ifdef DEBUG + #define DEBUG_BEGIN(x) Serial.begin (x) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINT_DEC(x) Serial.print (x, DEC) #define DEBUG_PRINT_HEX(x) Serial.print (x, HEX) #define DEBUG_PRINTLN(x) Serial.println (x) #define DEBUG_PRINT_STR(x) Serial.print (F(x)) #define DEBUG_PRINTLN_STR(x) Serial.println (F(x)) -#else +#else*/ + #define DEBUG_BEGIN(x) #define DEBUG_PRINT(x) #define DEBUG_PRINT_DEC(x) #define DEBUG_PRINT_HEX(x) #define DEBUG_PRINTLN(x) #define DEBUG_PRINT_STR(x) #define DEBUG_PRINTLN_STR(x) -#endif +//#endif // Shield configuration -#define USE_SPI 0x00 -#define USE_UART 0x01 -#define USE_I2C 0x02 -#define INT_NONE 0x00 -#define INT_0 0x01 -#define INT_1 0x02 -#define INT_BOTH 0x03 +#define USE_SPI 0x00 +#define USE_UART 0x01 +#define USE_I2C 0x02 +#define INT_NONE 0x00 +#define INT_0 0x01 +#define INT_1 0x02 +#define INT_BOTH 0x03 // UART configuration -#define UART_STOPBIT_1 0x01 -#define UART_STOPBIT_1_5 0x02 -#define UART_STOPBIT_2 0x03 -#define UART_PARITY_NONE 0x00 -#define UART_PARITY_ODD 0x01 -#define UART_PARITY_EVEN 0x02 -#define UART_FLOW_NONE 0x00 -#define UART_FLOW_RTS 0x01 -#define UART_FLOW_CTS 0x02 -#define UART_FLOW_BOTH 0x03 +#define UART_STOPBIT_1 0x01 +#define UART_STOPBIT_1_5 0x02 +#define UART_STOPBIT_2 0x03 +#define UART_PARITY_NONE 0x00 +#define UART_PARITY_ODD 0x01 +#define UART_PARITY_EVEN 0x02 +#define UART_FLOW_NONE 0x00 +#define UART_FLOW_RTS 0x01 +#define UART_FLOW_CTS 0x02 +#define UART_FLOW_BOTH 0x03 // Common error codes -#define ERR_NONE 0x00 -#define ERR_UNKNOWN 0x63 // maximum error code value is 99, so that it does not interfere with HTTP status codes +#define ERR_NONE 0x00 +#define ERR_UNKNOWN 0x63 // maximum error code value is 99, so that it does not interfere with HTTP status codes // SX1278/SX1272/RF69 error codes -#define ERR_CHIP_NOT_FOUND 0x01 -#define ERR_EEPROM_NOT_INITIALIZED 0x02 -#define ERR_PACKET_TOO_LONG 0x03 -#define ERR_TX_TIMEOUT 0x04 -#define ERR_RX_TIMEOUT 0x05 -#define ERR_CRC_MISMATCH 0x06 -#define ERR_INVALID_BANDWIDTH 0x07 -#define ERR_INVALID_SPREADING_FACTOR 0x08 -#define ERR_INVALID_CODING_RATE 0x09 -#define ERR_INVALID_BIT_RANGE 0x10 +#define ERR_CHIP_NOT_FOUND 0x01 +#define ERR_EEPROM_NOT_INITIALIZED 0x02 +#define ERR_PACKET_TOO_LONG 0x03 +#define ERR_TX_TIMEOUT 0x04 +#define ERR_RX_TIMEOUT 0x05 +#define ERR_CRC_MISMATCH 0x06 +#define ERR_INVALID_BANDWIDTH 0x07 +#define ERR_INVALID_SPREADING_FACTOR 0x08 +#define ERR_INVALID_CODING_RATE 0x09 +#define ERR_INVALID_BIT_RANGE 0x10 // ESP8266 error codes -#define ERR_AT_FAILED 0x01 -#define ERR_URL_MALFORMED 0x02 -#define ERR_RESPONSE_MALFORMED_AT 0x03 -#define ERR_RESPONSE_MALFORMED 0x04 -#define ERR_MQTT_CONNECTION_REFUSED 0x05 +#define ERR_AT_FAILED 0x01 +#define ERR_URL_MALFORMED 0x02 +#define ERR_RESPONSE_MALFORMED_AT 0x03 +#define ERR_RESPONSE_MALFORMED 0x04 +#define ERR_MQTT_CONN_VERSION_REJECTED 0x05 +#define ERR_MQTT_CONN_ID_REJECTED 0x06 +#define ERR_MQTT_CONN_SERVER_UNAVAILABLE 0x07 +#define MQTT_CONN_BAD_USERNAME_PASSWORD 0x08 +#define ERR_MQTT_CONN_NOT_AUTHORIZED 0x09 // XBee error codes -#define ERR_CMD_MODE_FAILED 0x02 +#define ERR_CMD_MODE_FAILED 0x02 enum Slot {SlotA, SlotB}; diff --git a/src/modules/ESP8266.cpp b/src/modules/ESP8266.cpp index e57b71d6..f45012ff 100644 --- a/src/modules/ESP8266.cpp +++ b/src/modules/ESP8266.cpp @@ -1,8 +1,7 @@ #include "ESP8266.h" ESP8266::ESP8266(Module* module) { - portTcp = 80; // Default HTTP port (TCP application) - portUdp = 53; // Default DNS port (UDP application) + portHttp = 80; portMqtt = 1883; _mod = module; } @@ -59,14 +58,21 @@ uint8_t ESP8266::join(const char* ssid, const char* password) { } // join AP - String cmd = "AT+CWJAP_CUR=\""; - cmd += ssid; - cmd += "\",\""; - cmd += password; - cmd += "\""; + const char* atStr = "AT+CWJAP_CUR=\""; + uint8_t cmdLen = strlen(atStr) + strlen(ssid) + strlen(password) + 4; + + char* cmd = new char[cmdLen]; + strcpy(cmd, atStr); + strcat(cmd, ssid); + strcat(cmd, "\",\""); + strcat(cmd, password); + strcat(cmd, "\""); + if(!_mod->ATsendCommand(cmd)) { + delete[] cmd; return(ERR_AT_FAILED); } + delete[] cmd; // disable multiple connection mode if(!_mod->ATsendCommand("AT+CIPMUX=0")) { @@ -77,125 +83,217 @@ uint8_t ESP8266::join(const char* ssid, const char* password) { } uint16_t ESP8266::HttpGet(const char* url, String& response) { - String urlString(url); - // get the host address and endpoint - int32_t resourceIndex = urlString.indexOf("/", 7); - if(resourceIndex == -1) { - return(ERR_URL_MALFORMED); + char* httpPrefix = strstr(url, "http://"); + char* endpoint; + char* host; + if(httpPrefix != NULL) { + // find the host string + char* hostStart = strchr(url, '/'); + hostStart = strchr(hostStart + 1, '/'); + char* hostEnd = strchr(hostStart + 1, '/'); + host = new char[hostEnd - hostStart]; + strncpy(host, hostStart + 1, hostEnd - hostStart - 1); + host[hostEnd - hostStart - 1] = 0x00; + + // find the endpoint string + endpoint = new char[url + strlen(url) - hostEnd + 1]; + strcpy(endpoint, hostEnd); + } else { + // find the host string + char* hostEnd = strchr(url, '/'); + host = new char[hostEnd - url + 1]; + strncpy(host, url, hostEnd - url); + host[hostEnd - url] = 0x00; + + // find the endpoint string + endpoint = new char[url + strlen(url) - hostEnd + 1]; + strcpy(endpoint, hostEnd); } - String host = urlString.substring(7, resourceIndex); - String endpoint = urlString.substring(resourceIndex); // build the GET request - String request = "GET "; - request += endpoint; - request += " HTTP/1.1\r\nHost: "; - request += host; - request += "\r\n\r\n"; + char* request = new char[strlen(endpoint) + strlen(host) + 25]; + strcpy(request, "GET "); + strcat(request, endpoint); + strcat(request, " HTTP/1.1\r\nHost: "); + strcat(request, host); + strcat(request, "\r\n\r\n"); + + delete[] endpoint; // create TCP connection - uint8_t state = startTcp(host.c_str()); + uint8_t state = openTransportConnection(host, "TCP", portHttp); + delete[] host; if(state != ERR_NONE) { + delete[] request; return(state); } // send the GET request state = send(request); + delete[] request; if(state != ERR_NONE) { return(state); } + delay(1000); + + // get the response length + uint16_t numBytes = getNumBytes(); + if(numBytes == 0) { + return(ERR_RESPONSE_MALFORMED_AT); + } + // read the response - String raw = receive(); + char* raw = new char[numBytes]; + size_t rawLength = receive((uint8_t*)raw); + if(rawLength == 0) { + delete[] raw; + return(ERR_RESPONSE_MALFORMED); + } // close the TCP connection - state = closeTcp(); + state = closeTransportConnection(); if(state != ERR_NONE) { + delete[] raw; return(state); } - // parse the response - int32_t numBytesIndex = raw.indexOf(":"); - if(numBytesIndex == -1) { - return(ERR_RESPONSE_MALFORMED_AT); - } - response = raw.substring(numBytesIndex + 1); - - // return the HTTP status code - int32_t spaceIndex = response.indexOf(" "); - if(spaceIndex == -1) { + // get the response body + char* responseStart = strstr(raw, "\r\n"); + if(responseStart == NULL) { + delete[] raw; return(ERR_RESPONSE_MALFORMED); } - String statusString = response.substring(spaceIndex + 1, spaceIndex + 4); - return(statusString.toInt()); + char* responseStr = new char[raw + rawLength - responseStart - 1]; + strncpy(responseStr, responseStart + 2, raw + rawLength - responseStart - 1); + responseStr[raw + rawLength - responseStart - 2] = 0x00; + response = String(responseStr); + delete[] responseStr; + + // return the HTTP status code + char* statusStart = strchr(raw, ' '); + delete[] raw; + if(statusStart == NULL) { + return(ERR_RESPONSE_MALFORMED); + } + char statusStr[4]; + strncpy(statusStr, statusStart + 1, 3); + statusStr[3] = 0x00; + return(atoi(statusStr)); } -uint16_t ESP8266::HttpPost(const char* url, String content, String& response, const char* contentType) { - String urlString(url); - String contentTypeString(contentType); - +uint16_t ESP8266::HttpPost(const char* url, const char* content, String& response, const char* contentType) { // get the host address and endpoint - int32_t resourceIndex = urlString.indexOf("/", 7); - if(resourceIndex == -1) { - return(ERR_URL_MALFORMED); + char* httpPrefix = strstr(url, "http://"); + char* endpoint; + char* host; + if(httpPrefix != NULL) { + // find the host string + char* hostStart = strchr(url, '/'); + hostStart = strchr(hostStart + 1, '/'); + char* hostEnd = strchr(hostStart + 1, '/'); + host = new char[hostEnd - hostStart]; + strncpy(host, hostStart + 1, hostEnd - hostStart - 1); + host[hostEnd - hostStart - 1] = 0x00; + + // find the endpoint string + endpoint = new char[url + strlen(url) - hostEnd + 1]; + strcpy(endpoint, hostEnd); + } else { + // find the host string + char* hostEnd = strchr(url, '/'); + host = new char[hostEnd - url + 1]; + strncpy(host, url, hostEnd - url); + host[hostEnd - url] = 0x00; + + // find the endpoint string + endpoint = new char[url + strlen(url) - hostEnd + 1]; + strcpy(endpoint, hostEnd); } - String host = urlString.substring(7, resourceIndex); - String endpoint = urlString.substring(resourceIndex); // build the POST request - String request = "POST "; - request += endpoint; - request += " HTTP/1.1\r\nHost: "; - request += host; - request += "\r\nContent-Type: "; - request += contentTypeString; - request += "\r\nContent-length: "; - request += content.length(); - request += "\r\n\r\n"; + char contentLengthStr[8]; + itoa(strlen(content), contentLengthStr, 10); + char* request = new char[strlen(endpoint) + strlen(host) + strlen(contentType) + strlen(contentLengthStr) + strlen(content) + 64]; + strcpy(request, "POST "); + strcat(request, endpoint); + strcat(request, " HTTP/1.1\r\nHost: "); + strcat(request, host); + strcat(request, "\r\nContent-Type: "); + strcat(request, contentType); + strcat(request, "\r\nContent-length: "); + strcat(request, contentLengthStr); + strcat(request, "\r\n\r\n"); + strcat(request, content); + strcat(request, "\r\n\r\n"); + + delete[] endpoint; // create TCP connection - uint8_t state = startTcp(host.c_str()); + uint8_t state = openTransportConnection(host, "TCP", portHttp); + delete[] host; if(state != ERR_NONE) { return(state); } // send the POST request state = send(request); + delete[] request; if(state != ERR_NONE) { return(state); } - // close the TCP connection - state = closeTcp(); - if(state != ERR_NONE) { - return(state); + delay(2000); + + // get the response length + uint16_t numBytes = getNumBytes(); + if(numBytes == 0) { + return(ERR_RESPONSE_MALFORMED_AT); } // read the response - String raw = receive(); - - // parse the response - int32_t numBytesIndex = raw.indexOf(":"); - if(numBytesIndex == -1) { - return(ERR_RESPONSE_MALFORMED_AT); - } - response = raw.substring(numBytesIndex + 1); - - // return the HTTP status code - int32_t spaceIndex = response.indexOf(" "); - if(spaceIndex == -1) { + char* raw = new char[numBytes]; + size_t rawLength = receive((uint8_t*)raw); + if(rawLength == 0) { + delete[] raw; return(ERR_RESPONSE_MALFORMED); } - String statusString = response.substring(spaceIndex + 1, spaceIndex + 4); - return(statusString.toInt()); + + // close the TCP connection + state = closeTransportConnection(); + if(state != ERR_NONE) { + delete[] raw; + return(state); + } + + // get the response body + char* responseStart = strstr(raw, "\r\n"); + if(responseStart == NULL) { + delete[] raw; + return(ERR_RESPONSE_MALFORMED); + } + char* responseStr = new char[raw + rawLength - responseStart - 1]; + strncpy(responseStr, responseStart + 2, raw + rawLength - responseStart - 1); + responseStr[raw + rawLength - responseStart - 2] = 0x00; + response = String(responseStr); + delete[] responseStr; + + // return the HTTP status code + char* statusStart = strchr(raw, ' '); + delete[] raw; + if(statusStart == NULL) { + return(ERR_RESPONSE_MALFORMED); + } + char statusStr[4]; + strncpy(statusStr, statusStart + 1, 3); + statusStr[3] = 0x00; + return(atoi(statusStr)); } -uint8_t ESP8266::MqttConnect(String host, String clientId, String username, String password) { - _MqttHost = host; - +uint8_t ESP8266::MqttConnect(const char* host, const char* clientId, const char* username, const char* password) { // encode packet length - uint32_t len = 16 + clientId.length() + username.length() + password.length(); + uint32_t len = strlen(clientId) + strlen(username) + strlen(password) + 16; /*uint8_t encoded[] = {0, 0, 0, 0}; MqttEncodeLength(len, encoded);*/ @@ -213,114 +311,94 @@ uint8_t ESP8266::MqttConnect(String host, String clientId, String username, Stri packet[5] = 'Q'; packet[6] = 'T'; packet[7] = 'T'; - packet[8] = 0x04; //protocol level - packet[9] = 0b11000010; //flags: user name + password + clean session - packet[10] = 0x00; //keep-alive interval MSB - packet[11] = 0x3C; //keep-alive interval LSB + packet[8] = 0x04; // protocol level + packet[9] = 0b11000010; // flags: user name + password + clean session + packet[10] = 0x00; // keep-alive interval MSB + packet[11] = 0x3C; // keep-alive interval LSB packet[12] = 0x00; - packet[13] = clientId.length(); - for(uint8_t i = 0; i < clientId.length(); i++) { - packet[i + 14] = (uint8_t)clientId.charAt(i); - } + packet[13] = strlen(clientId); + memcpy(packet + 14, clientId, strlen(clientId)); - packet[14 + clientId.length()] = 0x00; - packet[15 + clientId.length()] = username.length(); - for(uint8_t i = 0; i < username.length(); i++) { - packet[i + 16 + clientId.length()] = (uint8_t)username.charAt(i); - } + packet[14 + strlen(clientId)] = 0x00; + packet[15 + strlen(clientId)] = strlen(username); + memcpy(packet + 16 + strlen(clientId), username, strlen(username)); - packet[16 + clientId.length() + username.length()] = 0x00; - packet[17 + clientId.length() + username.length()] = password.length(); - for(uint8_t i = 0; i < password.length(); i++) { - packet[i + 18 + clientId.length() + username.length()] = (uint8_t)password.charAt(i); - } + packet[16 + strlen(clientId) + strlen(username)] = 0x00; + packet[17 + strlen(clientId) + strlen(username)] = strlen(password); + memcpy(packet + 18 + strlen(clientId) + strlen(username), password, strlen(password)); // create TCP connection - uint8_t state = openTransportConnection(_MqttHost.c_str(), "TCP", portMqtt, 7200); + uint8_t state = openTransportConnection(host, "TCP", portMqtt, 7200); if(state != ERR_NONE) { + delete[] packet; return(state); } // send MQTT packet state = send(packet, len + 2); + delete[] packet; if(state != ERR_NONE) { return(state); } - // read the response - String raw = receive(); - - // parse the response - int32_t numBytesIndex = raw.indexOf(":"); - if(numBytesIndex == -1) { + // get the response length (MQTT response has to be 4 bytes long) + uint16_t numBytes = getNumBytes(); + if(numBytes != 4) { return(ERR_RESPONSE_MALFORMED_AT); } - uint8_t response[] = {0, 0, 0, 0}; - for(uint8_t i = 0; i < 4; i++) { - response[i] = raw.charAt(i + numBytesIndex + 1); + // read the response + uint8_t* response = new uint8_t[numBytes]; + receive(response); + if((response[0x00] == MQTT_CONNACK << 4) && (response[0x01] == 2)) { + uint8_t returnCode = response[0x03]; + delete[] response; + return(returnCode); } - if(response[3] != 0x00) { - return(ERR_MQTT_CONNECTION_REFUSED); - } - - return(ERR_NONE); + delete[] response; + return(ERR_RESPONSE_MALFORMED); } -uint8_t ESP8266::MqttPublish(String topic, String message) { +uint8_t ESP8266::MqttPublish(const char* topic, const char* message) { // encode packet length - uint32_t len = 2 + topic.length() + message.length(); + uint32_t len = 2 + strlen(topic) + strlen(message); // build the PUBLISH packet uint8_t* packet = new uint8_t[len + 2]; - packet[0] = (MQTT_PUBLISH << 4) & 0xFF; + packet[0] = (MQTT_PUBLISH << 4); packet[1] = len; - packet[2] = 0x00; - packet[3] = topic.length(); - for(uint8_t i = 0; i < topic.length(); i++) { - packet[i + 4] = (uint8_t)topic.charAt(i); - } - - for(uint8_t i = 0; i < message.length(); i++) { - packet[i + 4 + topic.length()] = (uint8_t)message.charAt(i); - } + packet[3] = strlen(topic); + memcpy(packet + 4, topic, strlen(topic)); + memcpy(packet + 4 + strlen(topic), message, strlen(message)); // send MQTT packet uint8_t state = send(packet, len + 2); - if(state != ERR_NONE) { - return(state); - } + delete[] packet; + return(state); - return(ERR_NONE); + //TODO: implement QoS > 0 and PUBACK response checking } -uint8_t ESP8266::startTcp(const char* host, uint16_t tcpKeepAlive) { - return(openTransportConnection(host, "TCP", portTcp, tcpKeepAlive)); -} - -uint8_t ESP8266::closeTcp() { - return(closeTransportConnection()); -} - -uint8_t ESP8266::startUdp(const char* host) { - return(openTransportConnection(host, "UDP", portUdp)); -} - -uint8_t ESP8266::closeUdp() { - return(closeTransportConnection()); -} - -uint8_t ESP8266::send(String data) { +uint8_t ESP8266::send(const char* data) { + // build AT command + char lenStr[8]; + itoa(strlen(data), lenStr, 10); + const char* atStr = "AT+CIPSEND="; + char* cmd = new char[strlen(atStr) + strlen(lenStr)]; + strcpy(cmd, atStr); + strcat(cmd, lenStr); + // send data length in bytes - String cmd = "AT+CIPSEND="; - cmd += data.length(); if(!_mod->ATsendCommand(cmd)) { + delete[] cmd; return(ERR_AT_FAILED); } + delete[] cmd; + // send data if(!_mod->ATsendCommand(data)) { return(ERR_AT_FAILED); @@ -330,13 +408,22 @@ uint8_t ESP8266::send(String data) { } uint8_t ESP8266::send(uint8_t* data, uint32_t len) { - // send data length in bytes - String cmd = "AT+CIPSEND="; - cmd += len; + // build AT command + char lenStr[8]; + itoa(len, lenStr, 10); + const char atStr[] = "AT+CIPSEND="; + char* cmd = new char[strlen(atStr) + strlen(lenStr)]; + strcpy(cmd, atStr); + strcat(cmd, lenStr); + + // send command and data length in bytes if(!_mod->ATsendCommand(cmd)) { + delete[] cmd; return(ERR_AT_FAILED); } + delete[] cmd; + // send data if(!_mod->ATsendData(data, len)) { return(ERR_AT_FAILED); @@ -345,30 +432,13 @@ uint8_t ESP8266::send(uint8_t* data, uint32_t len) { return(ERR_NONE); } -String ESP8266::receive(uint32_t timeout) { - String data; - uint32_t start = millis(); - while(millis() - start < timeout) { - while(_mod->ModuleSerial->available() > 0) { - char c = _mod->ModuleSerial->read(); - #ifdef DEBUG - Serial.print(c); - #endif - data += c; - } - } - return(data); -} - -uint32_t ESP8266::receive(uint8_t* data, uint32_t timeout) { - uint8_t i = 0; +size_t ESP8266::receive(uint8_t* data, uint32_t timeout) { + size_t i = 0; uint32_t start = millis(); while(millis() - start < timeout) { while(_mod->ModuleSerial->available() > 0) { uint8_t b = _mod->ModuleSerial->read(); - #ifdef DEBUG - Serial.print(b); - #endif + DEBUG_PRINT(c); data[i] = b; i++; } @@ -377,19 +447,37 @@ uint32_t ESP8266::receive(uint8_t* data, uint32_t timeout) { } uint8_t ESP8266::openTransportConnection(const char* host, const char* protocol, uint16_t port, uint16_t tcpKeepAlive) { - String cmd = "AT+CIPSTART=\""; - cmd += protocol; - cmd += "\",\""; - cmd += host; - cmd += "\","; - cmd += port; - if((protocol == "TCP") && (tcpKeepAlive > 0)) { - cmd += ","; - cmd += tcpKeepAlive; + char portStr[6]; + itoa(port, portStr, 10); + char tcpKeepAliveStr[6]; + itoa(tcpKeepAlive, tcpKeepAliveStr, 10); + + const char* atStr = "AT+CIPSTART=\""; + uint8_t cmdLen = strlen(atStr) + strlen(protocol) + strlen(host) + strlen(portStr) + 5; + + if((strcmp(protocol, "TCP") == 0) && (tcpKeepAlive > 0)) { + cmdLen += strlen(tcpKeepAliveStr) + 1; } + + char* cmd = new char[cmdLen]; + strcpy(cmd, atStr); + strcat(cmd, protocol); + strcat(cmd, "\",\""); + strcat(cmd, host); + strcat(cmd, "\","); + strcat(cmd, portStr); + + if((strcmp(protocol, "TCP") == 0) && (tcpKeepAlive > 0)) { + strcat(cmd, ","); + strcat(cmd, tcpKeepAliveStr); + } + if(!_mod->ATsendCommand(cmd)) { + delete[] cmd; return(ERR_AT_FAILED); } + + delete[] cmd; return(ERR_NONE); } @@ -426,3 +514,43 @@ uint32_t ESP8266::MqttDecodeLength(uint8_t* encoded) { } while((encoded[i] & 128) != 0); return len; } + +uint16_t ESP8266::getNumBytes(uint32_t timeout) { + // wait for available data + uint32_t start = millis(); + while(_mod->ModuleSerial->available() < 10) { + if(millis() - start >= timeout) { + return(0); + } + } + + // read response + char rawStr[20]; + uint8_t i = 0; + start = millis(); + while(_mod->ModuleSerial->available() > 0) { + char c = _mod->ModuleSerial->read(); + rawStr[i++] = c; + if(c == ':') { + rawStr[i++] = 0; + break; + } + if(millis() - start >= timeout) { + rawStr[i++] = 0; + break; + } + } + + // get the number of bytes in response + char* pch = strtok(rawStr, ",:"); + if(pch == NULL) { + return(0); + } + + pch = strtok(NULL, ",:"); + if(pch == NULL) { + return(0); + } + + return(atoi(pch)); +} diff --git a/src/modules/ESP8266.h b/src/modules/ESP8266.h index 5fbb881f..34901a9e 100644 --- a/src/modules/ESP8266.h +++ b/src/modules/ESP8266.h @@ -3,6 +3,7 @@ #include "Module.h" +// MQTT packet types #define MQTT_CONNECT 0x01 #define MQTT_CONNACK 0x02 #define MQTT_PUBLISH 0x03 @@ -23,7 +24,7 @@ class ESP8266 { ESP8266(Module* module); // Port numbers - uint16_t portTcp, portUdp, portMqtt; + uint16_t portHttp, portMqtt; // Basic methods uint8_t begin(long speed); @@ -32,31 +33,26 @@ class ESP8266 { // HTTP methods uint16_t HttpGet(const char* url, String& response); - uint16_t HttpPost(const char* url, String content, String& response, const char* contentType = ""); + uint16_t HttpPost(const char* url, const char* content, String& response, const char* contentType = "text/plain"); // MQTT methods - uint8_t MqttConnect(String host, String clientId, String username, String password); - uint8_t MqttPublish(String topic, String message); + uint8_t MqttConnect(const char* host, const char* clientId, const char* username, const char* password); + uint8_t MqttPublish(const char* topic, const char* message); // Transport layer methods - uint8_t startTcp(const char* host, uint16_t tcpKeepAlive = 0); - uint8_t closeTcp(); - uint8_t startUdp(const char* host); - uint8_t closeUdp(); - uint8_t send(String data); + uint8_t openTransportConnection(const char* host, const char* protocol, uint16_t port, uint16_t tcpKeepAlive = 0); + uint8_t closeTransportConnection(); + uint8_t send(const char* data); uint8_t send(uint8_t* data, uint32_t len); - String receive(uint32_t timeout = 10000); - uint32_t receive(uint8_t* data, uint32_t timeout = 10000); + size_t receive(uint8_t* data, uint32_t timeout = 10000); private: Module* _mod; - uint8_t openTransportConnection(const char* host, const char* protocol, uint16_t port, uint16_t tcpKeepAlive = 0); - uint8_t closeTransportConnection(); - - String _MqttHost; void MqttEncodeLength(uint32_t len, uint8_t* encoded); uint32_t MqttDecodeLength(uint8_t* encoded); + + uint16_t getNumBytes(uint32_t timeout = 10000); }; #endif