|
/*! \file src/ESP8266.cpp |
|
* \brief ESP8266 library implementation. |
|
* Copyright 2015 by Thomas Buck, Christian Högerle |
|
* \author Thomas Buck |
|
* \author Christian Högerle |
|
*/ |
|
|
|
#define LOG |
|
#define LOG_ALL_DATA |
|
|
|
#include "debug.h" |
|
#include "ESP8266.h" |
|
|
|
#define RESPONSE_OK "OK" |
|
#define RESPONSE_ERROR "ERROR" |
|
#define RESPONSE_RESET "ready" |
|
|
|
ESPIP::ESPIP(int _a, int _b, int _c, int _d) { |
|
if ((_a < 0) || (_a > 255)) { |
|
debugPrintf("ESPIP(%d, %d, %d, %d): invalid!\r\n", _a, _b, _c, _d); |
|
a = 0; |
|
} else { |
|
a = _a; |
|
} |
|
|
|
if ((_b < 0) || (_b > 255)) { |
|
debugPrintf("ESPIP(%d, %d, %d, %d): invalid!\r\n", _a, _b, _c, _d); |
|
b = 0; |
|
} else { |
|
b = _b; |
|
} |
|
|
|
if ((_c < 0) || (_c > 255)) { |
|
debugPrintf("ESPIP(%d, %d, %d, %d): invalid!\r\n", _a, _b, _c, _d); |
|
c = 0; |
|
} else { |
|
c = _c; |
|
} |
|
|
|
if ((_d < 0) || (_d > 255)) { |
|
debugPrintf("ESPIP(%d, %d, %d, %d): invalid!\r\n", _a, _b, _c, _d); |
|
d = 0; |
|
} else { |
|
d = _d; |
|
} |
|
} |
|
|
|
// ---------------------------------------------------------------------------- |
|
|
|
void ESP8266::checkAlive() { |
|
// Clear UART buffer |
|
com.rxBufferFlush(); |
|
|
|
// Wait until ESP is back and echoes sent characters |
|
do { |
|
com.putc('A'); |
|
while (!com.txBufferEmpty()); |
|
} while (com.getc() != 'A'); |
|
|
|
// Send dummy "AT" command |
|
com.puts("T\r\n"); |
|
|
|
// Check for OK Response |
|
while (true) { |
|
std::string res = readLine(); |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::checkAlive(): error!\r\n"); |
|
return; |
|
} else if (res == RESPONSE_OK) { |
|
debugPrintf("ESP::checkAlive(): done.\r\n"); |
|
return; |
|
} else { |
|
debugPrintf("ESP::checkAlive(): unexpected \"%s\"!\r\n", res.c_str()); |
|
} |
|
} |
|
} |
|
|
|
void ESP8266::sendCommand(const char* cmd) { |
|
#ifdef LOG_ALL_DATA |
|
debug.printf("ESP::sendCommand(\"%s\")\r\n", cmd); |
|
#endif |
|
|
|
// Send command |
|
com.printf("%s\r\n", cmd); |
|
|
|
// Read echoed characters back |
|
readLine(); |
|
} |
|
|
|
std::string ESP8266::readLine() { |
|
// Read until we get a non-empty line |
|
static char lineBuffer[1024]; |
|
com.gets(lineBuffer, 1024); |
|
std::string line(lineBuffer); |
|
|
|
// Strip \r\n at the end |
|
if ((line.length() < 2) || ((line.length() >= 2) && (line.length() <= 3) && (line[0] == '\r'))) { |
|
#ifdef LOG_ALL_DATA |
|
debug.printf("ESP::readLine(): empty line!\r\n"); |
|
#endif |
|
return readLine(); |
|
} else if (line[line.length() - 3] == '\r') { |
|
line.erase(line.length() - 3); |
|
} else if (line[line.length() - 2] == '\r') { |
|
line.erase(line.length() - 2); |
|
} |
|
|
|
#ifdef LOG_ALL_DATA |
|
debug.printf("ESP::readLine(): \"%s\"\r\n", line.c_str()); |
|
#endif |
|
|
|
return line; |
|
} |
|
|
|
void ESP8266::poll() { |
|
if (!com.readable()) { |
|
return; |
|
} |
|
|
|
bool shouldCallCallback = false; |
|
int id = -1; |
|
std::string data; |
|
char first = com.getc(); |
|
if ((first >= '0') && (first <= '9')) { |
|
// Connection opened or closed |
|
std::string ans = readLine(); |
|
if (ans == ",CONNECT") { |
|
debugPrintf("ESP::poll(): new connection %d!\r\n", (first - '0')); |
|
} else if (ans == ",CLOSED") { |
|
debugPrintf("ESP::poll(): closed connection %d!\r\n", (first - '0')); |
|
} else { |
|
debugPrintf("ESP::poll(): unexpected \"%c%s\"!\r\n", first, ans.c_str()); |
|
} |
|
} else if (first == 'r') { |
|
// The module has been reset |
|
std::string ans = readLine(); |
|
if (ans == "eady") { |
|
debugPrintf("ESP::poll(): reset detected!\r\n"); |
|
if (initFunc) { |
|
initFunc(*this); |
|
} else { |
|
debugPrintf("ESP::poll(): no initialization given!\r\n"); |
|
} |
|
} else { |
|
debugPrintf("ESP::poll(): unexpected \"r%s\"!\r\n", ans.c_str()); |
|
} |
|
} else if (first == '+') { |
|
// Data has been received |
|
std::string text; |
|
for (int i = 0; i < 4; i++) text += com.getc(); |
|
if (text == "IPD,") { |
|
// Read id and data length |
|
std::string header; |
|
while ((header.length() == 0) || (header[header.length() - 1] != ':')) { |
|
header += com.getc(); |
|
} |
|
// Parse id and length |
|
int size = 0; |
|
if (sscanf(header.c_str(), "%d,%d:", &id, &size) != 2) { |
|
debugPrintf("ESP::poll(): malformed \"%s\"\r\n", header.c_str()); |
|
return; |
|
} |
|
if ((id >= 0) && (size > 0)) { |
|
// Read data |
|
for (int i = 0; i < size; i++) { |
|
data += com.getc(); |
|
} |
|
// Remember that we should call main program |
|
shouldCallCallback = true; |
|
} |
|
debugPrintf("ESP::poll(): done.\r\n"); |
|
} else { |
|
debugPrintf("ESP::poll(): unexpected \"+%s\"\r\n", text.c_str()); |
|
} |
|
} else if ((first != '\r') && (first != '\n')) { |
|
debugPrintf("ESP::poll(): unexpected first '%c'!\r\n", first); |
|
} |
|
|
|
if (shouldCallCallback) { |
|
if (callback) { |
|
callback(*this, id, data); |
|
} |
|
} |
|
} |
|
|
|
void ESP8266::dumbTerminal() { |
|
debugPrintf("Now acting as ESP8266 terminal...\r\n"); |
|
debugPrintf("Press 3x 'q' to exit this mode!\r\n"); |
|
int n = 0; |
|
while (n < 3) { |
|
if (debug.readable()) { |
|
char c = debug.getc(); |
|
if (c == 'q') { |
|
n++; |
|
} else { |
|
n = 0; |
|
} |
|
com.putc(c); |
|
} |
|
if (com.readable()) { |
|
debug.putc(com.getc()); |
|
} |
|
wdt.kick(); |
|
} |
|
com.printf("\r\n"); |
|
readLine(); |
|
readLine(); |
|
debugPrintf("\r\nBack to main-loop!\r\n"); |
|
} |
|
|
|
void ESP8266::resetHardware() { |
|
debugPrintf("ESP::resetHardware(): toggling pin...\r\n"); |
|
resetPin = 0; |
|
wait_ms(50); |
|
resetPin = 1; |
|
wait_ms(50); |
|
std::string res = readLine(); |
|
while (res != RESPONSE_RESET) { |
|
if (res == RESPONSE_OK) { |
|
debugPrintf("ESP::resetHardware(): going to reset...\r\n"); |
|
} else if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::resetHardware(): error!\r\n"); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
debugPrintf("ESP::resetHardware(): back alive!\r\n"); |
|
checkAlive(); |
|
} |
|
|
|
void ESP8266::resetSoftware() { |
|
// Send Reset command |
|
debugPrintf("ESP::resetSoftware()\r\n"); |
|
sendCommand("AT+RST"); |
|
std::string res = readLine(); |
|
while (res != RESPONSE_RESET) { |
|
if (res == RESPONSE_OK) { |
|
debugPrintf("ESP::resetSoftware(): going to reset...\r\n"); |
|
} else if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::resetSoftware(): error!\r\n"); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
debugPrintf("ESP::resetSoftware(): back alive!\r\n"); |
|
checkAlive(); |
|
} |
|
|
|
void ESP8266::setMode(ESPMode mode) { |
|
if ((mode >= 1) && (mode <= 3)) { |
|
// Send command and read echoed characters |
|
debugPrintf("ESP::setMode(%d)\r\n", mode); |
|
com.printf("AT+CWMODE=%d\r\n", mode); |
|
readLine(); |
|
|
|
// Check response |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::setMode(%d): error!\r\n", mode); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
} else { |
|
debugPrintf("ESP::setMode(%d): invalid!\r\n", mode); |
|
} |
|
} |
|
|
|
ESPMode ESP8266::getMode() { |
|
sendCommand("AT+CWMODE?"); |
|
std::string answer = readLine(); |
|
|
|
// Check response |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::getMode(): error!\r\n"); |
|
return ESPMODE_UNKNOWN; |
|
} |
|
res = readLine(); |
|
} |
|
|
|
// Interpret answer |
|
if (answer.compare(0, 8, "+CWMODE:") == 0) { |
|
std::string num = answer.substr(8); |
|
if (num.length() == 1) { |
|
int n = num[0] - '0'; |
|
if ((n >= 1) && (n <= 3)) { |
|
return ESPMode(n); |
|
} |
|
} |
|
} |
|
|
|
return ESPMODE_UNKNOWN; |
|
} |
|
|
|
std::string ESP8266::getConnectedSSID() { |
|
sendCommand("AT+CWJAP?"); |
|
std::string answer = readLine(); |
|
|
|
// Check response |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
if (answer != "No AP") { |
|
debugPrintf("ESP::getConnectedSSID(): error!\r\n"); |
|
} else { |
|
debugPrintf("ESP::getConnectedSSID(): not connected.\r\n"); |
|
} |
|
return ""; |
|
} |
|
res = readLine(); |
|
} |
|
|
|
if (answer == "No AP") { |
|
debugPrintf("ESP::getConnectedSSID(): not connected.\r\n"); |
|
return ""; |
|
} |
|
|
|
// Interpret answer |
|
if (answer.compare(0, 8, "+CWJAP:\"") == 0) { |
|
std::string result = answer.substr(8, answer.length() - 9); |
|
debugPrintf("ESP::getConnectedSSID(): \"%s\"\r\n", result.c_str()); |
|
return result; |
|
} |
|
|
|
debugPrintf("ESP::getConnectedSSID(): malformed answer \"%s\"\r\n", answer.c_str()); |
|
return ""; |
|
} |
|
|
|
std::vector<ESPAccessPoint> ESP8266::listAccessPoints() { |
|
sendCommand("AT+CWLAP"); |
|
|
|
std::vector<std::string> answers; |
|
std::vector<ESPAccessPoint> ret; |
|
|
|
while (1) { |
|
std::string line = readLine(); |
|
if (line == RESPONSE_OK) { |
|
break; |
|
} else if (line == RESPONSE_ERROR) { |
|
debugPrintf("ESP::listAccessPoints(): error!\r\n"); |
|
return ret; |
|
} else if (line.length() > 0) { |
|
answers.emplace_back(line); |
|
} |
|
} |
|
|
|
for (std::string& str : answers) { |
|
int enc, sig, chan; |
|
char ssid[100], mac[100]; |
|
|
|
if (sscanf(str.c_str(), |
|
"+CWLAP:(%d,\"%100[^\"]\",%d,\"%100[^\"]\",%d)", |
|
&enc, ssid, &sig, mac, &chan) == 5) { |
|
if ((enc >= 0) && (enc <= 4)) { |
|
ret.emplace_back(ssid, mac, sig, chan, ESPEncryption(enc)); |
|
} else { |
|
debugPrintf("ESP::listAccessPoints(): unknown encryption %d!\r\n", enc); |
|
} |
|
} else { |
|
debugPrintf("ESP::listAccessPoints(): can't parse line \"%s\"!\r\n", str.c_str()); |
|
} |
|
} |
|
|
|
return ret; |
|
} |
|
|
|
void ESP8266::join(const char* ssid, const char* password) { |
|
if ((ssid == nullptr) || (ssid[0] == '\0')) { |
|
debugPrintf("ESP::join(nullptr, ...): invalid!\r\n"); |
|
return; |
|
} |
|
|
|
if ((password == nullptr) || (password[0] == '\0')) { |
|
com.printf("AT+CWJAP=\"%s\"\r\n", ssid); |
|
} else { |
|
com.printf("AT+CWJAP=\"%s\",\"%s\"\r\n", ssid, password); |
|
} |
|
readLine(); |
|
|
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::join(\"%s\", ...): error!\r\n", ssid); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
|
|
debugPrintf("ESP::join(\"%s\", ...) done.\r\n", ssid); |
|
} |
|
|
|
void ESP8266::disconnectAP() { |
|
sendCommand("AT+CWQAP"); |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::disconnectAP(): error!\r\n"); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
debugPrintf("ESP::disconnectAP(): done.\r\n"); |
|
} |
|
|
|
void ESP8266::setConnectionMode(bool multiple) { |
|
debugPrintf("ESP::setConnectionMode(%s)\r\n", multiple ? "true" : "false"); |
|
com.printf("AT+CIPMUX=%d\r\n", multiple ? 1 : 0); |
|
readLine(); |
|
|
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::setConnectionMode(%s): error!\r\n", multiple ? "true" : "false"); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
} |
|
|
|
ESPIP ESP8266::getAccessPointAddress() { |
|
int a = 0, b = 0, c = 0, d = 0; |
|
sendCommand("AT+CIPAP?"); |
|
std::string answer = readLine(); |
|
|
|
// Check response |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::getAccessPointAddress(): error!\r\n"); |
|
return ESPIP(a, b, c, d); |
|
} |
|
res = readLine(); |
|
} |
|
|
|
// Interpret answer |
|
if (answer.compare(0, 8, "+CIPAP:\"") == 0) { |
|
std::string result = answer.substr(8, answer.length() - 9); |
|
if (sscanf(result.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) == 4) { |
|
debugPrintf("ESP::getAccessPointAddress(): \"%s\"\r\n", result.c_str()); |
|
return ESPIP(a, b, c, d); |
|
} |
|
} |
|
|
|
debugPrintf("ESP::getAccessPointAddress(): malformed IP \"%s\"!\r\n", answer.c_str()); |
|
return ESPIP(a, b, c, d); |
|
} |
|
|
|
ESPIP ESP8266::getStationAddress() { |
|
int a = 0, b = 0, c = 0, d = 0; |
|
sendCommand("AT+CIPSTA?"); |
|
std::string answer = readLine(); |
|
|
|
// Check response |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::getStationAddress(): error!\r\n"); |
|
return ESPIP(a, b, c, d); |
|
} |
|
res = readLine(); |
|
} |
|
|
|
// Interpret answer |
|
if (answer.compare(0, 9, "+CIPSTA:\"") == 0) { |
|
std::string result = answer.substr(9, answer.length() - 10); |
|
if (sscanf(result.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) == 4) { |
|
debugPrintf("ESP::getStationAddress(): \"%s\"\r\n", result.c_str()); |
|
return ESPIP(a, b, c, d); |
|
} |
|
} |
|
|
|
debugPrintf("ESP::getStationAddress(): malformed IP \"%s\"!\r\n", answer.c_str()); |
|
return ESPIP(a, b, c, d); |
|
} |
|
|
|
std::vector<ESPIP> ESP8266::getConnectedAddresses() { |
|
std::vector<ESPIP> result; |
|
|
|
// TODO |
|
|
|
return result; |
|
} |
|
|
|
void ESP8266::setConnection(ESPIP ip, int port, int id, bool tcp) { |
|
// TODO |
|
} |
|
|
|
void ESP8266::sendData(int length, const char* data, int id) { |
|
if ((length <= 0) || (data == nullptr)) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): no data?!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
return; |
|
} |
|
|
|
if (length > 2048) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): buffer too large!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
length = 2048; |
|
} |
|
|
|
if ((id >= 0) && (id <= 4)) { |
|
com.printf("AT+CIPSEND=%d,%d\r\n", id, length); |
|
readLine(); |
|
} else { |
|
com.printf("AT+CIPSEND=%d\r\n", length); |
|
readLine(); |
|
} |
|
|
|
std::string answer = readLine(); |
|
if (answer != RESPONSE_OK) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): unexpected \"%s\"!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id, answer.c_str()); |
|
return; |
|
} |
|
|
|
char c1 = com.getc(); |
|
char c2 = com.getc(); |
|
if ((c1 == '>') && (c2 == ' ')) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): transmitting data...\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
for (int i = 0; i < length; i++) { |
|
com.putc(data[i]); |
|
} |
|
std::string res = readLine(); |
|
while (res != "SEND OK") { |
|
if (res == RESPONSE_OK) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): success?\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
return; |
|
} else if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): error!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
return; |
|
} else if (res == RESPONSE_RESET) { |
|
debugPrintf("ESP::sendData(%d, %s, %d): reset detected!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id); |
|
if (initFunc) { |
|
initFunc(*this); |
|
} |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
} else { |
|
debugPrintf("ESP::sendData(%d, %s, %d): unexpected \"%c%c\"!\r\n", length, |
|
(data != nullptr) ? "..." : "nullptr", id, c1, c2); |
|
} |
|
} |
|
|
|
void ESP8266::closeConnection(int id) { |
|
if ((id >= 0) && (id <= 4)) { |
|
com.printf("AT+CIPCLOSE=%d\r\n", id); |
|
readLine(); |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::closeConnection(%d): error!\r\n", id); |
|
return; |
|
} else if (res == "MUX=0") { |
|
debugPrintf("ESP::closeConnection(%d): wrong mode!\r\n", id); |
|
return; |
|
} else if (res == "link is not") { |
|
debugPrintf("ESP::closeConnection(%d): not open!\r\n", id); |
|
} |
|
res = readLine(); |
|
} |
|
} else if (id < 0) { |
|
sendCommand("AT+CIPCLOSE"); |
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::closeConnection(%d): error!\r\n"); |
|
return; |
|
} else if (res == "MUX=1") { |
|
debugPrintf("ESP::closeConnection(%d): wrong mode!\r\n"); |
|
return; |
|
} |
|
res = readLine(); |
|
} |
|
} else { |
|
debugPrintf("ESP::closeConnection(%d): invalid arg!\r\n", id); |
|
} |
|
} |
|
|
|
void ESP8266::setServer(bool open, int port) { |
|
if (!open) { |
|
sendCommand("AT+CIPSERVER=0"); |
|
std::string res = readLine(); |
|
if (res != "no change") { |
|
debugPrintf("ESP::setServer(%s, %d): need reset!\r\n", open ? "true" : "false", port); |
|
resetHardware(); |
|
resetSoftware(); |
|
} |
|
return; |
|
} |
|
|
|
if (port < 0) { |
|
sendCommand("AT+CIPSERVER=1"); |
|
} else { |
|
com.printf("AT+CIPSERVER=1,%d\r\n", port); |
|
readLine(); |
|
} |
|
|
|
std::string res = readLine(); |
|
while (res != RESPONSE_OK) { |
|
if (res == RESPONSE_ERROR) { |
|
debugPrintf("ESP::setServer(%s, %d): error!\r\n", open ? "true" : "false", port); |
|
return; |
|
} else if (res == "no change") { |
|
break; |
|
} |
|
res = readLine(); |
|
} |
|
} |
|
|
|
void ESP8266::setAccessPointParameters(const char* ssid, const char* password, |
|
int channel, ESPEncryption encryption) { |
|
if ((encryption != ESPENC_NONE) && (encryption != ESPENC_WPA_PSK) && (encryption != ESPENC_WPA2_PSK) && (encryption != ESPENC_WPA_WPA2_PSK)) { |
|
debugPrintf("ESP::setAccessPointParameters(\"%s\", \"%s\", %d, %d): invalid encryption!\r\n", |
|
(ssid != nullptr) ? ssid : "nullptr", (password != nullptr) ? password : "nullptr", |
|
channel, encryption); |
|
return; |
|
} |
|
|
|
if ((ssid == nullptr) || (ssid[0] == '\0')) { |
|
debugPrintf("ESP::setAccessPointParameters(\"%s\", \"%s\", %d, %d): missing SSID!\r\n", |
|
(ssid != nullptr) ? ssid : "nullptr", (password != nullptr) ? password : "nullptr", |
|
channel, encryption); |
|
return; |
|
} |
|
|
|
if (((password == nullptr) || (password[0] == '\0')) && (encryption == ESPENC_NONE)) { |
|
debugPrintf("ESP::setAccessPointParameters(\"%s\", \"%s\", %d, %d): password but no encryption!\r\n", |
|
(ssid != nullptr) ? ssid : "nullptr", (password != nullptr) ? password : "nullptr", |
|
channel, encryption); |
|
return; |
|
} |
|
|
|
// TODO! |
|
} |
|
|
|
ESPStatus ESP8266::getStatus() { |
|
sendCommand("AT+CIPSTATUS"); |
|
|
|
std::string text = readLine(); |
|
|
|
std::string ret = readLine(); |
|
while (ret != RESPONSE_OK) { |
|
if (ret == RESPONSE_ERROR) { |
|
debugPrintf("ESP::getStatus(): error!\r\n"); |
|
return ESPSTATUS_UNKNOWN; |
|
} |
|
} |
|
|
|
int stat; |
|
if (sscanf(text.c_str(), "STATUS:%d", &stat) == 1) { |
|
if ((stat >= 2) && (stat <= 4)) { |
|
return ESPStatus(stat); |
|
} else { |
|
debugPrintf("ESP::getStatus(): invalid status %d!\r\n", stat); |
|
} |
|
} else { |
|
debugPrintf("ESP::getStatus(): invalid response \"%s\"!\r\n", text.c_str()); |
|
} |
|
|
|
return ESPSTATUS_UNKNOWN; |
|
} |
|
|
|
std::vector<ESPConnection> ESP8266::getConnections() { |
|
std::vector<ESPConnection> result; |
|
|
|
sendCommand("AT+CIPSTATUS"); |
|
readLine(); // ignore status line |
|
|
|
std::vector<std::string> answers; |
|
while (true) { |
|
std::string s = readLine(); |
|
if (s == RESPONSE_OK) { |
|
break; |
|
} else if (s == RESPONSE_ERROR) { |
|
debugPrintf("ESP::getConnections(): error! Continuing...\r\n"); |
|
break; |
|
} else { |
|
answers.emplace_back(s); |
|
} |
|
} |
|
|
|
for (auto& s : answers) { |
|
int id, port, mode, a, b, c, d; |
|
char type[100]; |
|
|
|
if (sscanf(s.c_str(), "+CIPSTATUS:%d,\"%100[^\"]\",\"%d.%d.%d.%d\",%d,%d", |
|
&id, type, &a, &b, &c, &d, &port, &mode) == 8) { |
|
std::string t(type); |
|
ESPConnectionType nt = ESPCONTYPE_UNKNOWN; |
|
if (t == "TCP") { |
|
nt = ESPCONTYPE_TCP; |
|
} else if (t == "UDP") { |
|
nt = ESPCONTYPE_UDP; |
|
} else { |
|
debugPrintf("ESP::getConnections(): invalid type \"%s\"!\r\n", t.c_str()); |
|
} |
|
ESPConnectionMode m = ESPCONMODE_UNKNOWN; |
|
if (mode == 0) { |
|
m = ESPCONMODE_CLIENT; |
|
} else if (mode == 1) { |
|
m = ESPCONMODE_SERVER; |
|
} else { |
|
debugPrintf("ESP::getConnections(): invalid mode %d!\r\n", mode); |
|
} |
|
result.emplace_back(id, nt, ESPIP(a, b, c, d), port, m); |
|
} else { |
|
debugPrintf("ESP::getConnections(): invalid line \"%s\"!\r\n", s.c_str()); |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
void ESP8266::performFirmwareUpdate() { |
|
sendCommand("AT+CIUPDATE"); |
|
|
|
int errorCount = 0; |
|
do { |
|
int step; |
|
std::string res = readLine(); |
|
if (res == RESPONSE_RESET) { |
|
debugPrintf("ESP::performFirmwareUpdate(): reset detected.\r\n"); |
|
if (initFunc) { |
|
initFunc(*this); |
|
} |
|
return; |
|
} else if (res == RESPONSE_OK) { |
|
debugPrintf("ESP::performFirmwareUpdate(): success.\r\n"); |
|
return; |
|
} else if (res == RESPONSE_ERROR) { |
|
errorCount++; |
|
if (errorCount >= 2) { |
|
debugPrintf("ESP::performFirmwareUpdate(): error!\r\n"); |
|
return; |
|
} |
|
} else if (sscanf(res.c_str(), "+CIPUPDATE:%d", &step) == 1) { |
|
if (step == 1) { |
|
debugPrintf("ESP::performFirmwareUpdate(): found server...\r\n"); |
|
} else if (step == 2) { |
|
debugPrintf("ESP::performFirmwareUpdate(): connected to server...\r\n"); |
|
} else if (step == 3) { |
|
debugPrintf("ESP::performFirmwareUpdate(): loaded newest firmware...\r\n"); |
|
} else if (step == 4) { |
|
debugPrintf("ESP::performFirmwareUpdate(): started firmware upgrade...\r\n"); |
|
} else { |
|
debugPrintf("ESP::performFirmwareUpdate(): unexpected step %d!\r\n", step); |
|
} |
|
} else { |
|
debugPrintf("ESP::performFirmwareUpdate(): unexpected \"%s\"!\r\n", res.c_str()); |
|
} |
|
} while (true); |
|
} |
|
|