2018-03-05 16:08:42 +00:00
|
|
|
#include "ESP8266.h"
|
|
|
|
|
|
|
|
ESP8266::ESP8266(Module* module) {
|
2018-06-29 08:30:40 +00:00
|
|
|
portHttp = 80;
|
2018-04-10 18:49:44 +00:00
|
|
|
portMqtt = 1883;
|
2018-03-05 16:08:42 +00:00
|
|
|
_mod = module;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ESP8266::begin(long speed) {
|
2018-04-19 15:32:16 +00:00
|
|
|
// set module properties
|
2018-03-31 08:06:45 +00:00
|
|
|
_mod->AtLineFeed = "\r\n";
|
2018-03-05 16:08:42 +00:00
|
|
|
_mod->baudrate = speed;
|
|
|
|
_mod->init(USE_UART, INT_NONE);
|
2018-04-19 15:32:16 +00:00
|
|
|
|
|
|
|
// empty UART buffer (garbage data)
|
2018-03-05 16:08:42 +00:00
|
|
|
_mod->ATemptyBuffer();
|
2018-04-19 15:32:16 +00:00
|
|
|
|
|
|
|
// test AT setup
|
2018-03-05 16:08:42 +00:00
|
|
|
if(!_mod->ATsendCommand("AT")) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
2018-04-19 15:32:16 +00:00
|
|
|
|
2018-03-05 16:08:42 +00:00
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
uint8_t ESP8266::reset() {
|
|
|
|
// send the reset command
|
2018-03-05 16:08:42 +00:00
|
|
|
if(!_mod->ATsendCommand("AT+RST")) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// wait for the module to start
|
|
|
|
delay(2000);
|
|
|
|
|
2018-04-19 15:32:16 +00:00
|
|
|
// test AT setup
|
2018-03-05 16:08:42 +00:00
|
|
|
uint32_t start = millis();
|
|
|
|
while (millis() - start < 3000) {
|
|
|
|
if(!_mod->ATsendCommand("AT")) {
|
|
|
|
delay(100);
|
|
|
|
} else {
|
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ESP8266::join(const char* ssid, const char* password) {
|
|
|
|
// set mode to station + soft AP
|
|
|
|
if(!_mod->ATsendCommand("AT+CWMODE_CUR=3")) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
// reset the module
|
|
|
|
uint8_t state = reset();
|
2018-03-05 16:08:42 +00:00
|
|
|
if(state != ERR_NONE) {
|
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
// join AP
|
2018-06-29 08:30:40 +00:00
|
|
|
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, "\"");
|
2018-06-29 09:05:53 +00:00
|
|
|
|
|
|
|
bool res = _mod->ATsendCommand(cmd);
|
|
|
|
delete[] cmd;
|
|
|
|
if(!res) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// disable multiple connection mode
|
|
|
|
if(!_mod->ATsendCommand("AT+CIPMUX=0")) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
uint16_t ESP8266::HttpGet(const char* url, String& response) {
|
2018-03-05 16:08:42 +00:00
|
|
|
// get the host address and endpoint
|
2018-06-29 08:30:40 +00:00
|
|
|
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);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// build the GET request
|
2018-06-29 08:30:40 +00:00
|
|
|
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;
|
2018-03-05 16:08:42 +00:00
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
// create TCP connection
|
2018-06-29 08:30:40 +00:00
|
|
|
uint8_t state = openTransportConnection(host, "TCP", portHttp);
|
|
|
|
delete[] host;
|
2018-03-05 18:18:53 +00:00
|
|
|
if(state != ERR_NONE) {
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] request;
|
2018-03-05 18:18:53 +00:00
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-03-05 16:08:42 +00:00
|
|
|
// send the GET request
|
|
|
|
state = send(request);
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] request;
|
2018-03-05 16:08:42 +00:00
|
|
|
if(state != ERR_NONE) {
|
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
delay(1000);
|
|
|
|
|
|
|
|
// get the response length
|
|
|
|
uint16_t numBytes = getNumBytes();
|
|
|
|
if(numBytes == 0) {
|
|
|
|
return(ERR_RESPONSE_MALFORMED_AT);
|
|
|
|
}
|
|
|
|
|
2018-03-05 16:08:42 +00:00
|
|
|
// read the response
|
2018-06-29 08:30:40 +00:00
|
|
|
char* raw = new char[numBytes];
|
|
|
|
size_t rawLength = receive((uint8_t*)raw);
|
|
|
|
if(rawLength == 0) {
|
|
|
|
delete[] raw;
|
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
|
|
|
}
|
2018-03-05 16:08:42 +00:00
|
|
|
|
|
|
|
// close the TCP connection
|
2018-06-29 08:30:40 +00:00
|
|
|
state = closeTransportConnection();
|
2018-03-05 16:08:42 +00:00
|
|
|
if(state != ERR_NONE) {
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] raw;
|
2018-03-05 16:08:42 +00:00
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
// get the response body
|
|
|
|
char* responseStart = strstr(raw, "\r\n");
|
|
|
|
if(responseStart == NULL) {
|
|
|
|
delete[] raw;
|
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
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;
|
2018-03-05 16:08:42 +00:00
|
|
|
|
|
|
|
// return the HTTP status code
|
2018-06-29 08:30:40 +00:00
|
|
|
char* statusStart = strchr(raw, ' ');
|
|
|
|
delete[] raw;
|
|
|
|
if(statusStart == NULL) {
|
2018-03-05 16:08:42 +00:00
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
char statusStr[4];
|
|
|
|
strncpy(statusStr, statusStart + 1, 3);
|
|
|
|
statusStr[3] = 0x00;
|
|
|
|
return(atoi(statusStr));
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
uint16_t ESP8266::HttpPost(const char* url, const char* content, String& response, const char* contentType) {
|
2018-03-05 18:18:53 +00:00
|
|
|
// get the host address and endpoint
|
2018-06-29 08:30:40 +00:00
|
|
|
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);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
2018-03-05 18:18:53 +00:00
|
|
|
|
|
|
|
// build the POST request
|
2018-06-29 08:30:40 +00:00
|
|
|
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;
|
2018-03-05 18:18:53 +00:00
|
|
|
|
|
|
|
// create TCP connection
|
2018-06-29 08:30:40 +00:00
|
|
|
uint8_t state = openTransportConnection(host, "TCP", portHttp);
|
|
|
|
delete[] host;
|
2018-03-05 18:18:53 +00:00
|
|
|
if(state != ERR_NONE) {
|
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
// send the POST request
|
|
|
|
state = send(request);
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] request;
|
2018-03-05 18:18:53 +00:00
|
|
|
if(state != ERR_NONE) {
|
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
delay(2000);
|
|
|
|
|
|
|
|
// get the response length
|
|
|
|
uint16_t numBytes = getNumBytes();
|
|
|
|
if(numBytes == 0) {
|
|
|
|
return(ERR_RESPONSE_MALFORMED_AT);
|
|
|
|
}
|
|
|
|
|
|
|
|
// read the response
|
|
|
|
char* raw = new char[numBytes];
|
|
|
|
size_t rawLength = receive((uint8_t*)raw);
|
|
|
|
if(rawLength == 0) {
|
|
|
|
delete[] raw;
|
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
|
|
|
}
|
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
// close the TCP connection
|
2018-06-29 08:30:40 +00:00
|
|
|
state = closeTransportConnection();
|
2018-03-05 18:18:53 +00:00
|
|
|
if(state != ERR_NONE) {
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] raw;
|
2018-03-05 18:18:53 +00:00
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
// get the response body
|
|
|
|
char* responseStart = strstr(raw, "\r\n");
|
|
|
|
if(responseStart == NULL) {
|
|
|
|
delete[] raw;
|
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
2018-03-05 18:18:53 +00:00
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
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;
|
2018-03-05 18:18:53 +00:00
|
|
|
|
|
|
|
// return the HTTP status code
|
2018-06-29 08:30:40 +00:00
|
|
|
char* statusStart = strchr(raw, ' ');
|
|
|
|
delete[] raw;
|
|
|
|
if(statusStart == NULL) {
|
2018-03-05 18:18:53 +00:00
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
char statusStr[4];
|
|
|
|
strncpy(statusStr, statusStart + 1, 3);
|
|
|
|
statusStr[3] = 0x00;
|
|
|
|
return(atoi(statusStr));
|
2018-03-05 18:18:53 +00:00
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
uint8_t ESP8266::MqttConnect(const char* host, const char* clientId, const char* username, const char* password) {
|
2018-04-10 18:49:44 +00:00
|
|
|
// encode packet length
|
2018-06-29 08:30:40 +00:00
|
|
|
uint32_t len = strlen(clientId) + strlen(username) + strlen(password) + 16;
|
2018-04-10 18:49:44 +00:00
|
|
|
/*uint8_t encoded[] = {0, 0, 0, 0};
|
|
|
|
MqttEncodeLength(len, encoded);*/
|
|
|
|
|
|
|
|
// build the CONNECT packet
|
|
|
|
uint8_t* packet = new uint8_t[len + 2];
|
|
|
|
packet[0] = (MQTT_CONNECT << 4) & 0xFF;
|
|
|
|
packet[1] = len;
|
|
|
|
/*for(uint8_t i = 1; i < 4; i++) {
|
|
|
|
packet[i] = encoded[i];
|
|
|
|
}*/
|
|
|
|
|
|
|
|
packet[2] = 0x00;
|
|
|
|
packet[3] = 0x04;
|
|
|
|
packet[4] = 'M';
|
|
|
|
packet[5] = 'Q';
|
|
|
|
packet[6] = 'T';
|
|
|
|
packet[7] = 'T';
|
2018-06-29 08:30:40 +00:00
|
|
|
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
|
2018-04-10 18:49:44 +00:00
|
|
|
|
|
|
|
packet[12] = 0x00;
|
2018-06-29 08:30:40 +00:00
|
|
|
packet[13] = strlen(clientId);
|
|
|
|
memcpy(packet + 14, clientId, strlen(clientId));
|
2018-04-10 18:49:44 +00:00
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
packet[14 + strlen(clientId)] = 0x00;
|
|
|
|
packet[15 + strlen(clientId)] = strlen(username);
|
|
|
|
memcpy(packet + 16 + strlen(clientId), username, strlen(username));
|
2018-04-10 18:49:44 +00:00
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
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));
|
2018-04-10 18:49:44 +00:00
|
|
|
|
|
|
|
// create TCP connection
|
2018-06-29 08:30:40 +00:00
|
|
|
uint8_t state = openTransportConnection(host, "TCP", portMqtt, 7200);
|
2018-04-10 18:49:44 +00:00
|
|
|
if(state != ERR_NONE) {
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] packet;
|
2018-04-10 18:49:44 +00:00
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
// send MQTT packet
|
|
|
|
state = send(packet, len + 2);
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] packet;
|
2018-04-10 18:49:44 +00:00
|
|
|
if(state != ERR_NONE) {
|
|
|
|
return(state);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
// get the response length (MQTT response has to be 4 bytes long)
|
|
|
|
uint16_t numBytes = getNumBytes();
|
|
|
|
if(numBytes != 4) {
|
2018-04-10 18:49:44 +00:00
|
|
|
return(ERR_RESPONSE_MALFORMED_AT);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
// 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);
|
2018-04-10 18:49:44 +00:00
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] response;
|
|
|
|
return(ERR_RESPONSE_MALFORMED);
|
2018-04-10 18:49:44 +00:00
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
uint8_t ESP8266::MqttPublish(const char* topic, const char* message) {
|
2018-04-10 18:49:44 +00:00
|
|
|
// encode packet length
|
2018-06-29 08:30:40 +00:00
|
|
|
uint32_t len = 2 + strlen(topic) + strlen(message);
|
2018-04-10 18:49:44 +00:00
|
|
|
|
|
|
|
// build the PUBLISH packet
|
|
|
|
uint8_t* packet = new uint8_t[len + 2];
|
2018-06-29 08:30:40 +00:00
|
|
|
packet[0] = (MQTT_PUBLISH << 4);
|
2018-04-10 18:49:44 +00:00
|
|
|
packet[1] = len;
|
|
|
|
packet[2] = 0x00;
|
2018-06-29 08:30:40 +00:00
|
|
|
packet[3] = strlen(topic);
|
|
|
|
memcpy(packet + 4, topic, strlen(topic));
|
|
|
|
memcpy(packet + 4 + strlen(topic), message, strlen(message));
|
2018-04-10 18:49:44 +00:00
|
|
|
|
|
|
|
// send MQTT packet
|
|
|
|
uint8_t state = send(packet, len + 2);
|
2018-06-29 08:30:40 +00:00
|
|
|
delete[] packet;
|
|
|
|
return(state);
|
2018-04-10 18:49:44 +00:00
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
//TODO: implement QoS > 0 and PUBACK response checking
|
2018-04-10 18:49:44 +00:00
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
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);
|
|
|
|
|
2018-03-05 16:08:42 +00:00
|
|
|
// send data length in bytes
|
2018-06-29 09:05:53 +00:00
|
|
|
bool res = _mod->ATsendCommand(cmd);
|
|
|
|
delete[] cmd;
|
|
|
|
if(!res) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// send data
|
|
|
|
if(!_mod->ATsendCommand(data)) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 16:08:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
|
2018-04-10 18:49:44 +00:00
|
|
|
uint8_t ESP8266::send(uint8_t* data, uint32_t len) {
|
2018-06-29 08:30:40 +00:00
|
|
|
// 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
|
2018-06-29 09:05:53 +00:00
|
|
|
bool res = _mod->ATsendCommand(cmd);
|
|
|
|
delete[] cmd;
|
|
|
|
if(!res) {
|
2018-04-10 18:49:44 +00:00
|
|
|
return(ERR_AT_FAILED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// send data
|
|
|
|
if(!_mod->ATsendData(data, len)) {
|
|
|
|
return(ERR_AT_FAILED);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
|
2018-06-29 08:30:40 +00:00
|
|
|
size_t ESP8266::receive(uint8_t* data, uint32_t timeout) {
|
|
|
|
size_t i = 0;
|
2018-04-10 18:49:44 +00:00
|
|
|
uint32_t start = millis();
|
|
|
|
while(millis() - start < timeout) {
|
|
|
|
while(_mod->ModuleSerial->available() > 0) {
|
|
|
|
uint8_t b = _mod->ModuleSerial->read();
|
2018-06-29 08:30:40 +00:00
|
|
|
DEBUG_PRINT(c);
|
2018-04-10 18:49:44 +00:00
|
|
|
data[i] = b;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ESP8266::openTransportConnection(const char* host, const char* protocol, uint16_t port, uint16_t tcpKeepAlive) {
|
2018-06-29 08:30:40 +00:00
|
|
|
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;
|
2018-04-10 18:49:44 +00:00
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-06-29 09:05:53 +00:00
|
|
|
bool res = _mod->ATsendCommand(cmd);
|
|
|
|
delete[] cmd;
|
|
|
|
if(!res) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 18:18:53 +00:00
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
|
2018-03-05 18:18:53 +00:00
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ESP8266::closeTransportConnection() {
|
|
|
|
if(!_mod->ATsendCommand("AT+CIPCLOSE")) {
|
2018-03-09 10:14:15 +00:00
|
|
|
return(ERR_AT_FAILED);
|
2018-03-05 18:18:53 +00:00
|
|
|
}
|
|
|
|
return(ERR_NONE);
|
|
|
|
}
|
2018-04-10 18:49:44 +00:00
|
|
|
|
|
|
|
void ESP8266::MqttEncodeLength(uint32_t len, uint8_t* encoded) {
|
|
|
|
uint8_t i = 0;
|
|
|
|
do {
|
|
|
|
encoded[i] = len % 128;
|
|
|
|
len /= 128;
|
|
|
|
if(len > 0) {
|
|
|
|
encoded[i] |= 128;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
} while(len > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t ESP8266::MqttDecodeLength(uint8_t* encoded) {
|
|
|
|
uint32_t mult = 1;
|
|
|
|
uint32_t len = 0;
|
|
|
|
uint8_t i = 0;
|
|
|
|
do {
|
|
|
|
len += (encoded[i] & 127) * mult;
|
|
|
|
mult *= 128;
|
|
|
|
if(mult > 2097152) {
|
|
|
|
// malformed remaining length
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
} while((encoded[i] & 128) != 0);
|
|
|
|
return len;
|
|
|
|
}
|
2018-06-29 08:30:40 +00:00
|
|
|
|
|
|
|
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));
|
|
|
|
}
|