MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification
Dependencies: MaximInterface mbed
The MAXREFDES143# is an Internet of Things (IoT) embedded security reference design, built to protect an industrial sensing node by means of authentication and notification to a web server. The hardware includes a peripheral module representing a protected sensor node monitoring operating temperature and remaining life of a filter (simulated through ambient light sensing) and an mbed shield representing a controller node responsible for monitoring one or more sensor nodes. The design is hierarchical with each controller node communicating data from connected sensor nodes to a web server that maintains a centralized log and dispatches notifications as necessary. The mbed shield contains a Wi-Fi module, a DS2465 coprocessor with 1-Wire® master function, an LCD, LEDs, and pushbuttons. The protected sensor node contains a DS28E15 authenticator, a DS7505 temperature sensor, and a MAX44009 light sensor. The mbed shield communicates to a web server by the onboard Wi-Fi module and to the protected sensor node with I2C and 1-Wire. The MAXREFDES143# is equipped with a standard shield connector for immediate testing using an mbed board such as the MAX32600MBED#. The simplicity of this design enables rapid integration into any star-topology IoT network requiring the heightened security with low overhead provided by the SHA-256 symmetric-key algorithm.
More information about the MAXREFDES143# is available on the Maxim Integrated website.
Revision 29:590a7561318b, committed 2017-01-26
- Comitter:
- IanBenzMaxim
- Date:
- Thu Jan 26 16:55:23 2017 -0600
- Parent:
- 28:e5cdaf13d299
- Child:
- 30:0784010d6975
- Commit message:
- Rollback to mbed 2 for stability until online compiler issues with mbed 5 can be resolved.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266.cpp Thu Jan 26 16:55:23 2017 -0600
@@ -0,0 +1,489 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include <cstdlib>
+#include "ESP8266.hpp"
+#include "Timer.h"
+#include "wait_api.h"
+
+ESP8266* ESP8266::defaultInstance = NULL;
+
+static inline void disableRecvData()
+{
+ __disable_irq();
+}
+
+static inline void enableRecvData()
+{
+ __enable_irq();
+}
+
+void ESP8266::setDefaultInstance(ESP8266 * const instance)
+{
+ if (instance != NULL)
+ defaultInstance = instance;
+}
+
+ESP8266** ESP8266::getDefaultInstance()
+{
+ return &defaultInstance;
+}
+
+ESP8266::ESP8266(const PinName tx, const PinName rx, const PinName rst, const PinName CH_PD, const int baud, mbed::Serial * debugMsgIntf)
+ : AT_intf(tx, rx), resetPin(rst), powerDownPin(CH_PD), debugMsg(debugMsgIntf), parseRecvReset(false)
+{
+ AT_intf.baud(baud);
+ AT_intf.attach(this, &ESP8266::recv_AT_data_cb);
+
+ // Ensure that device is not held in reset
+ if (resetPin.is_connected())
+ resetPin = 1;
+ // Power down device at startup due to high current demand
+ setPowered(false);
+
+ if (defaultInstance == NULL)
+ defaultInstance = this;
+}
+
+ESP8266::~ESP8266()
+{
+ if (defaultInstance == this)
+ defaultInstance = NULL;
+}
+
+void ESP8266::reset()
+{
+ if (resetPin.is_connected())
+ {
+ resetPin = 0;
+ wait_ms(100);
+ resetPin = 1;
+ wait_ms(1000);
+ }
+}
+
+bool ESP8266::powered() const
+{
+ bool isPowered;
+ if (powerDownPin.is_connected())
+ {
+ isPowered = powerDownPin.read();
+ }
+ else
+ {
+ isPowered = false;
+ }
+ return isPowered;
+}
+
+void ESP8266::setPowered(bool powered)
+{
+ if (powerDownPin.is_connected())
+ powerDownPin = powered;
+}
+
+ESP8266::CmdResult ESP8266::performSelfTest()
+{
+ return sendCommand(CmdBuilder(""));
+}
+
+ESP8266::CmdResult ESP8266::setCurrentWifiMode(const ESP8266::WifiMode mode)
+{
+ CmdBuilder builder("CWMODE_CUR");
+ builder.addRawArgument(mode);
+ return sendCommand(builder);
+}
+
+ESP8266::CmdResult ESP8266::joinCurrentAccessPoint(const std::string & ssid, const std::string & pwd, const std::string & bssid)
+{
+ CmdBuilder builder("CWJAP_CUR");
+ builder.addStringArgument(ssid);
+ builder.addStringArgument(pwd);
+ if (bssid != "")
+ builder.addStringArgument(bssid);
+ return sendCommand(builder);
+}
+
+ESP8266::CmdResult ESP8266::quitAccessPoint()
+{
+ return sendCommand(CmdBuilder("CWQAP"));
+}
+
+ESP8266::CmdResult ESP8266::setMaxRFTXPower(const float power_dBm)
+{
+ int power_arg = (int)(power_dBm * 4);
+ if (power_arg > 82)
+ power_arg = 82;
+ else if (power_arg < 0)
+ power_arg = 0;
+
+ CmdBuilder builder("RFPOWER");
+ builder.addRawArgument(power_arg);
+ return sendCommand(builder);
+}
+
+ESP8266::CmdResult ESP8266::ping(const std::string & IP)
+{
+ CmdBuilder builder("PING");
+ builder.addStringArgument(IP);
+ return sendCommand(builder);
+}
+
+ESP8266::CmdResult ESP8266::openConnection(const ESP8266::ConnType type, const std::string & remoteIP, const unsigned int remotePort)
+{
+ CmdBuilder builder("CIPSTART");
+ builder.addStringArgument((type == TCP) ? "TCP" : "UDP");
+ builder.addStringArgument(remoteIP);
+ builder.addRawArgument(remotePort);
+ return sendCommand(builder);
+}
+
+ESP8266::CmdResult ESP8266::closeConnection()
+{
+ return sendCommand(CmdBuilder("CIPCLOSE"));
+}
+
+ESP8266::CmdResult ESP8266::sendData(const std::string & data)
+{
+ CmdBuilder builder("CIPSEND");
+ builder.addRawArgument(data.length());
+ ESP8266::CmdResult result = sendCommand(builder);
+ if (result == ESP8266::AT_OK)
+ result = send_AT_data(data, false);
+ return result;
+}
+
+ESP8266::CmdResult ESP8266::sendCommand(const CmdBuilder & cmd)
+{
+ return send_AT_data(cmd.str(), true);
+}
+
+bool ESP8266::recvIpDataReadable()
+{
+ bool result;
+
+ disableRecvData(); // Lock queue access
+
+ result = !recvIpDataBuffer.empty();
+
+ enableRecvData(); // Unlock queue access
+
+ return result;
+}
+
+char ESP8266::getcRecvIpData()
+{
+ char received;
+
+ disableRecvData(); // Lock queue access
+
+ // Pop next char or set to NTC if not data in buffer
+ if (!recvIpDataBuffer.pop(received))
+ received = '\0';
+
+ enableRecvData(); // Unlock queue access
+
+ return received;
+}
+
+void ESP8266::clearRecvData()
+{
+ disableRecvData(); // Lock queue access
+
+ recvIpDataBuffer.reset();
+ parseRecvReset = true;
+
+ enableRecvData(); // Unlock queue access
+}
+
+ESP8266::CmdResult ESP8266::send_AT_data(const std::string & cmdString, const bool expectEcho)
+{
+ const int timeout_ms = 10000;
+
+ mbed::Timer timer;
+ ESP8266::CmdResult result = ESP8266::HardwareError;
+ std::string response;
+
+ disableRecvData(); // Lock for manual data handling in this procedure
+
+ // Flush receive buffer
+ while (AT_intf.readable())
+ AT_intf.getc();
+
+ // Begin counting for timeout
+ timer.start();
+
+ for (size_t i = 0; i < cmdString.length(); i++)
+ {
+ // Write next character
+ while (!AT_intf.writeable())
+ {
+ if (timer.read_ms() > timeout_ms)
+ {
+ result = TimeoutError;
+ goto exit;
+ }
+ }
+ AT_intf.putc(cmdString[i]);
+ // Wait for echo
+ if (expectEcho && (cmdString[i] != '\r') && (cmdString[i] != '\n'))
+ {
+ while (!AT_intf.readable())
+ {
+ if (timer.read_ms() > timeout_ms)
+ {
+ result = TimeoutError;
+ goto exit;
+ }
+ }
+ // Compare to written character
+ if (AT_intf.getc() != cmdString[i])
+ {
+ // Handle error
+ result = ESP8266::HardwareError;
+ goto exit;
+ }
+ }
+ }
+
+ while (result == ESP8266::HardwareError)
+ {
+ // Wait to receive something
+ response.clear();
+ while (!read_line(response)) ;
+
+ // Check if valid response
+ if (response == "OK")
+ result = ESP8266::AT_OK;
+ else if (response == "FAIL")
+ result = ESP8266::AT_FAIL;
+ else if (response == "ERROR")
+ result = ESP8266::AT_ERROR;
+ else if (response == "SEND OK") // Used by AT+CIPSEND
+ result = ESP8266::AT_OK;
+ else if (response == "ALREADY CONNECT") // Used by AT+CIPSTART
+ result = ESP8266::AT_OK;
+
+ if (timer.read_ms() > timeout_ms)
+ {
+ result = TimeoutError;
+ break;
+ }
+ }
+
+exit:
+ enableRecvData(); // Enable interrupt processing
+ return result;
+}
+
+bool ESP8266::read_line(std::string & line)
+{
+ char received;
+
+ while (AT_intf.readable())
+ {
+ received = AT_intf.getc();
+ if (received == '\n')
+ {
+ return true;
+ }
+ else if (received != '\r')
+ {
+ line.push_back(received);
+ }
+ }
+ return false;
+}
+
+void ESP8266::recv_AT_data_cb()
+{
+ while (AT_intf.readable())
+ {
+ char received = AT_intf.getc();
+ parseRecvIpData(received);
+ parseRecvConnClosedMsg(received);
+ parseRecvReset = false;
+ }
+}
+
+void ESP8266::parseRecvIpData(const char received)
+{
+ enum DataRecvState
+ {
+ Header,
+ Length,
+ Data,
+ Reset
+ };
+
+ static const char findChars[] = "+IPD,";
+ static const size_t maxSizeDigits = 4;
+
+ static size_t dataFinishedSize = 0;
+ static size_t index = 0;
+ static char sizeDigits[] = { '\0', '\0', '\0', '\0', '\0' };
+ static DataRecvState state = Header;
+
+ if (parseRecvReset)
+ state = Reset;
+
+ switch (state)
+ {
+ case Reset:
+ default:
+ index = 0;
+ dataFinishedSize = 0;
+ state = Header;
+ // Continue processing switch
+
+ case Header:
+ if (received == findChars[index])
+ {
+ if (findChars[++index] == '\0')
+ {
+ index = 0;
+ state = Length;
+ }
+ }
+ else
+ {
+ state = Reset;
+ }
+ break;
+
+ case Length:
+ if ((received <= '9') && (received >= '0'))
+ {
+ if (index < maxSizeDigits)
+ {
+ sizeDigits[index++] = received;
+ }
+ else
+ {
+ state = Reset;
+ }
+ }
+ else if (received == ':')
+ {
+ dataFinishedSize = std::atoi(sizeDigits);
+ if (dataFinishedSize == 0)
+ {
+ state = Reset;
+ }
+ else
+ {
+ index = 0;
+ state = Data;
+ }
+ }
+ else
+ {
+ state = Reset;
+ }
+ break;
+
+ case Data:
+ if (index < dataFinishedSize)
+ {
+ recvIpDataBuffer.push(received);
+ index++;
+ }
+ else
+ {
+ state = Reset;
+ }
+ break;
+ };
+}
+
+void ESP8266::parseRecvConnClosedMsg(const char received)
+{
+ static const char findChars[] = "CLOSED";
+
+ static int index = 0;
+
+ bool shouldReset = parseRecvReset;
+
+ if (received == findChars[index])
+ {
+ if (findChars[++index] == '\0')
+ {
+ printDbgMsg(findChars);
+ shouldReset = true;
+ }
+ }
+ else
+ {
+ shouldReset = true;
+ }
+
+ if (shouldReset)
+ {
+ index = 0;
+ }
+}
+
+void ESP8266::printDbgMsg(const char * message)
+{
+ if (debugMsg != NULL)
+ debugMsg->printf("%s", message);
+}
+
+ESP8266::CmdBuilder::CmdBuilder(const std::string & cmd)
+{
+ clear(cmd);
+}
+
+void ESP8266::CmdBuilder::clear(const std::string & cmd)
+{
+ numArgs = 0;
+ cmdStream.str("");
+
+ cmdStream << "AT";
+ if (cmd != "")
+ cmdStream << "+" << cmd;
+}
+
+void ESP8266::CmdBuilder::addStringArgument(const std::string & arg)
+{
+ std::ostringstream argStream;
+ argStream << "\"" << arg << "\"";
+ addRawArgument<std::string>(argStream.str());
+}
+
+std::string ESP8266::CmdBuilder::str() const
+{
+ std::string cmdString = cmdStream.str();
+ cmdString.append("\r\n");
+ return cmdString;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266.hpp Thu Jan 26 16:55:23 2017 -0600
@@ -0,0 +1,220 @@
+/*******************************************************************************
+* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef ESP8266_HPP
+#define ESP8266_HPP
+
+#include <string>
+#include <sstream>
+
+#include "PinNames.h"
+#include "Serial.h"
+#include "DigitalOut.h"
+#include "CircularBuffer.h"
+
+namespace mbed { class Serial; }
+
+/// Interface to the ESP8266 Wi-Fi module.
+class ESP8266
+{
+public:
+ /// Result of sending an AT command.
+ enum CmdResult
+ {
+ AT_OK = 1,
+ AT_FAIL = 0,
+ AT_ERROR = -1,
+ HardwareError = -2,
+ TimeoutError = -3
+ };
+
+ /// ESP8266 Wi-Fi mode.
+ enum WifiMode
+ {
+ station_mode = 1,
+ softAP_mode = 2,
+ softAP_station_mode = 3
+ };
+
+ /// Connection type.
+ enum ConnType
+ {
+ TCP,
+ UDP
+ };
+
+ /// Recovery time between Send Data operation as specified by datasheet.
+ static const unsigned int sendDataRecoveryTimeMs = 1000;
+
+ /// Builds command strings for the ESP8266 with proper formatting.
+ class CmdBuilder
+ {
+ public:
+ /// @param cmd Command of the format "AT+[cmd]".
+ CmdBuilder(const std::string & cmd = "");
+
+ /// Clear all arguments.
+ /// @param cmd Command of the format "AT+[cmd]".
+ void clear(const std::string & cmd);
+
+ /// Append an argument using the default string conversion for that type.
+ /// @param arg Argument to append to the command.
+ template <typename T> void addRawArgument(const T & arg)
+ {
+ cmdStream << ((numArgs == 0) ? "=" : ",") << arg;
+ numArgs++;
+ }
+
+ /// Append a string argument with proper quoting.
+ /// @param arg Argument to append to the command.
+ void addStringArgument(const std::string & arg);
+
+ /// Create a string suitable for use with sendCommand().
+ /// @returns The formatted command string.
+ std::string str() const;
+
+ private:
+ int numArgs;
+ std::ostringstream cmdStream;
+ };
+
+ /// @{
+ /// Default instance support for use with mbed Sockets.
+ static void setDefaultInstance(ESP8266 * const instance);
+ static ESP8266** getDefaultInstance();
+ /// @}
+
+ /// @param tx Transmit pin from mbed to ESP8266.
+ /// @param rx Receive pin from ESP8266 to mbed.
+ /// @param rst Reset pin on ESP8266.
+ /// @param CH_PD Power-down pin on ESP8266.
+ /// @param baud Baud rate that the ESP8266 is using.
+ /// @param debugMsgIntf Optional serial interface for debugging messages.
+ ESP8266(const PinName tx, const PinName rx, const PinName rst, const PinName CH_PD, const int baud, mbed::Serial * debugMsgIntf = NULL);
+ ~ESP8266();
+
+ /// Reset the ESP8266 via the hardware reset pin.
+ void reset();
+
+ // Update the baud rate for the ESP8266.
+ void setBaud(int baud) { AT_intf.baud(baud); }
+
+ /// @{
+ /// Control if the ESP8266 is powered via the hardware power-down pin.
+ bool powered() const;
+ void setPowered(bool powered);
+ /// @}
+
+ /// Perform a self-test on the ESP8266.
+ CmdResult performSelfTest();
+
+ /// Set the current Wi-Fi mode.
+ CmdResult setCurrentWifiMode(const WifiMode mode);
+
+ /// Join a Wi-Fi access point.
+ /// @param ssid Network SSID to connect to.
+ /// @param pwd Network password.
+ /// @param bssid Optional network BSSID.
+ CmdResult joinCurrentAccessPoint(const std::string & ssid, const std::string & pwd, const std::string & bssid = "");
+
+ /// Quit the current access point.
+ CmdResult quitAccessPoint();
+
+ /// Set the maximum WiFi tranmission power.
+ /// @param power_dBm Power in dBm valid from 0 to 20.5 in 0.25 dBm increments.
+ CmdResult setMaxRFTXPower(const float power_dBm);
+
+ /// Ping a host via the current access point.
+ /// @param IP IP address or resolvable hostname.
+ CmdResult ping(const std::string & IP);
+
+ /// Open a connection to a host via the current access point.
+ /// @param type TCP or UPD connection.
+ /// @param remoteIP IP address or resolvable hostname to connect to.
+ /// @param remotePort Port on the host to connect to.
+ CmdResult openConnection(const ConnType type, const std::string & remoteIP, const unsigned int remotePort);
+
+ /// Close the connection to the current host.
+ CmdResult closeConnection();
+
+ /// Send data to the currently connected host.
+ /// @param data May be in text or binary form.
+ CmdResult sendData(const std::string & data);
+
+ /// Send an AT command to the ESP8266.
+ /// @param cmd Formatted command to send.
+ CmdResult sendCommand(const CmdBuilder & cmd);
+
+ /// Check if received IP data is available in the buffer.
+ /// @note Allow some processing delay to happen between calls to this function.
+ /// @returns True if data is available.
+ bool recvIpDataReadable();
+ /// Get the next character of received IP data from the buffer.
+ char getcRecvIpData();
+ /// Clear all received data from the buffer.
+ void clearRecvData();
+
+private:
+ static ESP8266 * defaultInstance; ///< Default instance support for use with mbed Sockets.
+
+ mbed::Serial AT_intf;
+ mbed::DigitalOut resetPin;
+ mutable mbed::DigitalOut powerDownPin; ///< @note Mark as mutable for use in powered().
+ mbed::CircularBuffer<char, 1024> recvIpDataBuffer; ///< Received IP data buffer.
+ mbed::Serial * debugMsg;
+ volatile bool parseRecvReset; ///< Indicates when AT interface received data parsers should be reset.
+
+ /// Send raw AT data to the ESP8266.
+ /// @param cmdString Data to send.
+ /// @param expectEcho True if the ESP8266 will echo sent data back.
+ CmdResult send_AT_data(const std::string & cmdString, const bool expectEcho);
+
+ /// Attempts to read an entire line terminated with \r\n from the AT interface.
+ /// \r will be preserved in the final string and \n will be stripped.
+ /// @param line Buffer to store received characters in.
+ /// @returns True if an entire line was read.
+ bool read_line(std::string & line);
+
+ /// Callback for when data is received on the AT interface.
+ void recv_AT_data_cb();
+ /// Parse the next character received on the AT interface checking for valid IP data.
+ void parseRecvIpData(const char received);
+ /// Parse the next character receive on the AT interface for the connection closed message.
+ void parseRecvConnClosedMsg(const char received);
+
+ /// Print a message on the debugging interface if setup.
+ /// @param message Null terminated string.
+ void printDbgMsg(const char * message);
+};
+
+#endif
\ No newline at end of file
--- a/WebServerInterface.cpp Thu Jan 26 14:18:21 2017 -0600
+++ b/WebServerInterface.cpp Thu Jan 26 16:55:23 2017 -0600
@@ -31,11 +31,9 @@
*******************************************************************************
*/
-#include <sstream>
#include <vector>
#include "WebServerInterface.hpp"
-#include "NetworkStack.h"
-#include "TCPSocket.h"
+#include "ESP8266.hpp"
#include "Slaves/Authenticators/ISha256MacCoproc.h"
#include "SensorData.hpp"
#include "HexConversions.hpp"
@@ -44,6 +42,8 @@
using OneWire::ISha256MacCoproc;
+const char WebServerInterface::wifiSsid[] = "TWS iPhone";
+const char WebServerInterface::wifiPassword[] = "maxim1234";
const char WebServerInterface::serverAddress[] = "www.mxim-security.us";
const unsigned int WebServerInterface::serverPort = 80;
const char WebServerInterface::serverPostPath[] = "/post.php";
@@ -71,6 +71,26 @@
return (MacCoproc.computeSlaveSecret(fillData, fillData, secretData) == ISha256MacCoproc::Success);
}
+bool WebServerInterface::initialize()
+{
+ esp8266.setPowered(true);
+ esp8266.reset();
+ bool result = (esp8266.performSelfTest() == ESP8266::AT_OK);
+ if (result)
+ {
+ result = (esp8266.setCurrentWifiMode(ESP8266::softAP_station_mode) == ESP8266::AT_OK);
+ }
+ if (result)
+ {
+ result = (esp8266.setMaxRFTXPower(10) == ESP8266::AT_OK);
+ }
+ if (result)
+ {
+ result = (esp8266.joinCurrentAccessPoint(wifiSsid, wifiPassword) == ESP8266::AT_OK);
+ }
+ return result;
+}
+
/// Format an HTTP GET request as a string for transmission.
/// @param host Web server address.
/// @param path Web server location to retrieve.
@@ -215,7 +235,13 @@
bool WebServerInterface::authPostHttpEvent(ISha256MacCoproc & macCoproc, PostEvent event, const std::string & postData, bool setSecret)
{
+ const std::string challengeSearch(newline + newline);
bool result;
+ uint8_t challenge[challengeLen];
+ std::string response;
+
+ std::memset(challenge, defaultPaddingByte, challengeLen);
+ response.reserve(300);
if (setSecret)
{
@@ -225,47 +251,58 @@
}
// Open connection
- TCPSocket socket(&networkStack);
- result = (socket.connect(serverAddress, 80) == 0);
+ esp8266.clearRecvData(); // Clear received data buffer
+ result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) == ESP8266::AT_OK);
if (result)
{
// Request challenge
- std::string httpData = formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString);
- result = (socket.send(httpData.data(), httpData.size()) == httpData.size());
+ result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString)) == ESP8266::AT_OK);
if (result)
{
// Receive server response
- int recvResult = socket.recv(recvBuf, sizeof(recvBuf) / sizeof(recvBuf[0]));
- result = recvResult > 0;
-
- if (result)
- {
- // Parse challenge from response
- const std::string challengeSearch(newline + newline);
- httpData.assign(recvBuf, recvResult);
- size_t challengePos = httpData.find(challengeSearch);
- if ((challengePos != std::string::npos) && ((challengePos + challengeSearch.length() + (challengeLen * charsPerByte)) <= httpData.length()))
+ for (int i = 0; i < 10; i++)
+ {
+ while (esp8266.recvIpDataReadable())
{
- uint8_t challenge[challengeLen];
- challengePos += challengeSearch.length();
- for (size_t i = 0; i < challengeLen; i++)
+ char read = esp8266.getcRecvIpData();
+ if (response.length() < response.capacity())
{
- std::sscanf(httpData.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]);
+ response += read;
}
-
- // Post sensor data
- httpData = formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge);
- result = (socket.send(httpData.data(), httpData.size()) == httpData.size());
- if (result)
+ else
{
- result = (socket.recv(recvBuf, sizeof(recvBuf) / sizeof(recvBuf[0])) >= 0);
+ wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
+ goto close_get_connection;
}
}
+ wait_ms(100);
+ }
+ // Close connection
+ close_get_connection:
+ esp8266.closeConnection();
+
+ // Parse challenge from response
+ size_t challengePos = response.find(challengeSearch);
+ if ((challengePos != std::string::npos) && ((challengePos + challengeSearch.length() + (challengeLen * charsPerByte)) <= response.length()))
+ {
+ challengePos += challengeSearch.length();
+ for (size_t i = 0; i < challengeLen; i++)
+ {
+ std::sscanf(response.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]);
+ }
+ }
+
+ // Post sensor data
+ result = (esp8266.openConnection(ESP8266::TCP, serverAddress, serverPort) == ESP8266::AT_OK);
+ if (result)
+ {
+ result = (esp8266.sendData(formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge)) == ESP8266::AT_OK);
+ wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
}
}
// Close connection
- socket.close();
+ esp8266.closeConnection();
}
return result;
--- a/WebServerInterface.hpp Thu Jan 26 14:18:21 2017 -0600
+++ b/WebServerInterface.hpp Thu Jan 26 16:55:23 2017 -0600
@@ -46,7 +46,7 @@
namespace mbed { class Serial; }
namespace OneWire { class ISha256MacCoproc; }
-class NetworkStack;
+class ESP8266;
struct SensorData;
/// Network interface to the web server supporting authenticated posting of event
@@ -56,7 +56,11 @@
public:
/// @param esp8266 Interface to ESP8266 for Wi-Fi access.
/// @param pc Optional serial interface for received web traffic.
- WebServerInterface(NetworkStack & networkStack) : networkStack(networkStack) { }
+ WebServerInterface(ESP8266 & esp8266) : esp8266(esp8266) { }
+
+ /// Initialize network interface and connect to access point.
+ /// @returns True on success.
+ bool initialize();
/// Send an authenticated event message to the web server.
/// @param macCoProc Coprocessor such as the DS2465 used to calculate the authentication MAC.
@@ -81,6 +85,8 @@
private:
/// @{
/// Configuration strings.
+ static const char wifiSsid[];
+ static const char wifiPassword[];
static const char serverAddress[];
static const unsigned int serverPort;
static const char serverPostPath[];
@@ -90,9 +96,7 @@
OneWire::RomId m_sessionId;
std::string m_sessionIdString;
- NetworkStack & networkStack;
-
- char recvBuf[1024];
+ ESP8266 & esp8266;
};
#endif
\ No newline at end of file
--- a/esp8266-driver/ESP8266/ATParser.lib Thu Jan 26 14:18:21 2017 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://github.com/ARMmbed/ATParser/#269f14532b98442669c50383782cbce1c67aced5
--- a/esp8266-driver/ESP8266/ESP8266.cpp Thu Jan 26 14:18:21 2017 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-/* ESP8266 Example
- * Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ESP8266.h"
-
-ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
- : _serial(tx, rx, 1024), _parser(_serial)
- , _packets(0), _packets_end(&_packets)
-{
- _serial.baud(38400);
- _parser.debugOn(debug);
-}
-
-bool ESP8266::startup(int mode)
-{
- //only 3 valid modes
- if(mode < 1 || mode > 3) {
- return false;
- }
-
- bool success = reset()
- && _parser.send("AT+RFPOWER=10")
- && _parser.recv("OK")
- && _parser.send("AT+CWMODE_CUR=%d", mode)
- && _parser.recv("OK")
- && _parser.send("AT+CIPMUX=1")
- && _parser.recv("OK");
-
- _parser.oob("+IPD", this, &ESP8266::_packet_handler);
-
- return success;
-}
-
-bool ESP8266::reset(void)
-{
- return _parser.send("AT+RST")
- && _parser.recv("ready");
-}
-
-bool ESP8266::dhcp(bool enabled, int mode)
-{
- //only 3 valid modes
- if(mode < 0 || mode > 2) {
- return false;
- }
-
- return _parser.send("AT+CWDHCP_CUR=%d,%d", enabled?1:0, mode)
- && _parser.recv("OK");
-}
-
-bool ESP8266::connect(const char *ap, const char *passPhrase)
-{
- return _parser.send("AT+CWJAP_CUR=\"%s\",\"%s\"", ap, passPhrase)
- && _parser.recv("OK");
-}
-
-bool ESP8266::disconnect(void)
-{
- return _parser.send("AT+CWQAP") && _parser.recv("OK");
-}
-
-const char *ESP8266::getIPAddress(void)
-{
- if (!(_parser.send("AT+CIFSR")
- && _parser.recv("+CIFSR:STAIP,\"%15[^\"]\"", _ip_buffer)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- return _ip_buffer;
-}
-
-const char *ESP8266::getMACAddress(void)
-{
- if (!(_parser.send("AT+CIFSR")
- && _parser.recv("+CIFSR:STAMAC,\"%17[^\"]\"", _mac_buffer)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- return _mac_buffer;
-}
-
-const char *ESP8266::getGateway()
-{
- if (!(_parser.send("AT+CIPSTA?")
- && _parser.recv("+CIPSTA:gateway:\"%15[^\"]\"", _gateway_buffer)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- return _gateway_buffer;
-}
-
-const char *ESP8266::getNetmask()
-{
- if (!(_parser.send("AT+CIPSTA?")
- && _parser.recv("+CIPSTA:netmask:\"%15[^\"]\"", _netmask_buffer)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- return _netmask_buffer;
-}
-
-int8_t ESP8266::getRSSI()
-{
- int8_t rssi;
- char bssid[18];
-
- if (!(_parser.send("AT+CWJAP?")
- && _parser.recv("+CWJAP:\"%*[^\"]\",\"%17[^\"]\"", bssid)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- if (!(_parser.send("AT+CWLAP=\"\",\"%s\",", bssid)
- && _parser.recv("+CWLAP:(%*d,\"%*[^\"]\",%hhd,", &rssi)
- && _parser.recv("OK"))) {
- return 0;
- }
-
- return rssi;
-}
-
-bool ESP8266::isConnected(void)
-{
- return getIPAddress() != 0;
-}
-
-int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
-{
- unsigned cnt = 0;
- nsapi_wifi_ap_t ap;
-
- if (!_parser.send("AT+CWLAP")) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
-
- while (recv_ap(&ap)) {
- if (cnt < limit) {
- res[cnt] = WiFiAccessPoint(ap);
- }
-
- cnt++;
- if (limit != 0 && cnt >= limit) {
- break;
- }
- }
-
- return cnt;
-}
-
-bool ESP8266::open(const char *type, int id, const char* addr, int port)
-{
- //IDs only 0-4
- if(id > 4) {
- return false;
- }
-
- return _parser.send("AT+CIPSTART=%d,\"%s\",\"%s\",%d", id, type, addr, port)
- && _parser.recv("OK");
-}
-
-bool ESP8266::send(int id, const void *data, uint32_t amount)
-{
- //May take a second try if device is busy
- for (unsigned i = 0; i < 2; i++) {
- if (_parser.send("AT+CIPSEND=%d,%d", id, amount)
- && _parser.recv(">")
- && _parser.write((char*)data, (int)amount) >= 0) {
- return true;
- }
- }
-
- return false;
-}
-
-void ESP8266::_packet_handler()
-{
- int id;
- uint32_t amount;
-
- // parse out the packet
- if (!_parser.recv(",%d,%d:", &id, &amount)) {
- return;
- }
-
- struct packet *packet = (struct packet*)malloc(
- sizeof(struct packet) + amount);
- if (!packet) {
- return;
- }
-
- packet->id = id;
- packet->len = amount;
- packet->next = 0;
-
- if (!(_parser.read((char*)(packet + 1), amount))) {
- free(packet);
- return;
- }
-
- // append to packet list
- *_packets_end = packet;
- _packets_end = &packet->next;
-}
-
-int32_t ESP8266::recv(int id, void *data, uint32_t amount)
-{
- while (true) {
- // check if any packets are ready for us
- for (struct packet **p = &_packets; *p; p = &(*p)->next) {
- if ((*p)->id == id) {
- struct packet *q = *p;
-
- if (q->len <= amount) { // Return and remove full packet
- memcpy(data, q+1, q->len);
-
- if (_packets_end == &(*p)->next) {
- _packets_end = p;
- }
- *p = (*p)->next;
-
- uint32_t len = q->len;
- free(q);
- return len;
- } else { // return only partial packet
- memcpy(data, q+1, amount);
-
- q->len -= amount;
- memmove(q+1, (uint8_t*)(q+1) + amount, q->len);
-
- return amount;
- }
- }
- }
-
- // Wait for inbound packet
- if (!_parser.recv("OK")) {
- return -1;
- }
- }
-}
-
-bool ESP8266::close(int id)
-{
- //May take a second try if device is busy
- for (unsigned i = 0; i < 2; i++) {
- if (_parser.send("AT+CIPCLOSE=%d", id)
- && _parser.recv("OK")) {
- return true;
- }
- }
-
- return false;
-}
-
-void ESP8266::setTimeout(uint32_t timeout_ms)
-{
- _parser.setTimeout(timeout_ms);
-}
-
-bool ESP8266::readable()
-{
- return _serial.readable();
-}
-
-bool ESP8266::writeable()
-{
- return _serial.writeable();
-}
-
-void ESP8266::attach(Callback<void()> func)
-{
- _serial.attach(func);
-}
-
-bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
-{
- int sec;
- bool ret = _parser.recv("+CWLAP:(%d,\"%32[^\"]\",%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\",%d", &sec, ap->ssid,
- &ap->rssi, &ap->bssid[0], &ap->bssid[1], &ap->bssid[2], &ap->bssid[3], &ap->bssid[4],
- &ap->bssid[5], &ap->channel);
-
- ap->security = sec < 5 ? (nsapi_security_t)sec : NSAPI_SECURITY_UNKNOWN;
-
- return ret;
-}
--- a/esp8266-driver/ESP8266/ESP8266.h Thu Jan 26 14:18:21 2017 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/* ESP8266Interface Example
- * Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ESP8266_H
-#define ESP8266_H
-
-#include "ATParser.h"
-
-/** ESP8266Interface class.
- This is an interface to a ESP8266 radio.
- */
-class ESP8266
-{
-public:
- ESP8266(PinName tx, PinName rx, bool debug=false);
-
- /**
- * Startup the ESP8266
- *
- * @param mode mode of WIFI 1-client, 2-host, 3-both
- * @return true only if ESP8266 was setup correctly
- */
- bool startup(int mode);
-
- /**
- * Reset ESP8266
- *
- * @return true only if ESP8266 resets successfully
- */
- bool reset(void);
-
- /**
- * Enable/Disable DHCP
- *
- * @param enabled DHCP enabled when true
- * @param mode mode of DHCP 0-softAP, 1-station, 2-both
- * @return true only if ESP8266 enables/disables DHCP successfully
- */
- bool dhcp(bool enabled, int mode);
-
- /**
- * Connect ESP8266 to AP
- *
- * @param ap the name of the AP
- * @param passPhrase the password of AP
- * @return true only if ESP8266 is connected successfully
- */
- bool connect(const char *ap, const char *passPhrase);
-
- /**
- * Disconnect ESP8266 from AP
- *
- * @return true only if ESP8266 is disconnected successfully
- */
- bool disconnect(void);
-
- /**
- * Get the IP address of ESP8266
- *
- * @return null-teriminated IP address or null if no IP address is assigned
- */
- const char *getIPAddress(void);
-
- /**
- * Get the MAC address of ESP8266
- *
- * @return null-terminated MAC address or null if no MAC address is assigned
- */
- const char *getMACAddress(void);
-
- /** Get the local gateway
- *
- * @return Null-terminated representation of the local gateway
- * or null if no network mask has been recieved
- */
- const char *getGateway();
-
- /** Get the local network mask
- *
- * @return Null-terminated representation of the local network mask
- * or null if no network mask has been recieved
- */
- const char *getNetmask();
-
- /* Return RSSI for active connection
- *
- * @return Measured RSSI
- */
- int8_t getRSSI();
-
- /**
- * Check if ESP8266 is conenected
- *
- * @return true only if the chip has an IP address
- */
- bool isConnected(void);
-
- /** Scan for available networks
- *
- * @param ap Pointer to allocated array to store discovered AP
- * @param limit Size of allocated @a res array, or 0 to only count available AP
- * @return Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
- * see @a nsapi_error
- */
- int scan(WiFiAccessPoint *res, unsigned limit);
-
- /**
- * Open a socketed connection
- *
- * @param type the type of socket to open "UDP" or "TCP"
- * @param id id to give the new socket, valid 0-4
- * @param port port to open connection with
- * @param addr the IP address of the destination
- * @return true only if socket opened successfully
- */
- bool open(const char *type, int id, const char* addr, int port);
-
- /**
- * Sends data to an open socket
- *
- * @param id id of socket to send to
- * @param data data to be sent
- * @param amount amount of data to be sent - max 1024
- * @return true only if data sent successfully
- */
- bool send(int id, const void *data, uint32_t amount);
-
- /**
- * Receives data from an open socket
- *
- * @param id id to receive from
- * @param data placeholder for returned information
- * @param amount number of bytes to be received
- * @return the number of bytes received
- */
- int32_t recv(int id, void *data, uint32_t amount);
-
- /**
- * Closes a socket
- *
- * @param id id of socket to close, valid only 0-4
- * @return true only if socket is closed successfully
- */
- bool close(int id);
-
- /**
- * Allows timeout to be changed between commands
- *
- * @param timeout_ms timeout of the connection
- */
- void setTimeout(uint32_t timeout_ms);
-
- /**
- * Checks if data is available
- */
- bool readable();
-
- /**
- * Checks if data can be written
- */
- bool writeable();
-
- /**
- * Attach a function to call whenever network state has changed
- *
- * @param func A pointer to a void function, or 0 to set as none
- */
- void attach(Callback<void()> func);
-
- /**
- * Attach a function to call whenever network state has changed
- *
- * @param obj pointer to the object to call the member function on
- * @param method pointer to the member function to call
- */
- template <typename T, typename M>
- void attach(T *obj, M method) {
- attach(Callback<void()>(obj, method));
- }
-
-private:
- BufferedSerial _serial;
- ATParser _parser;
-
- struct packet {
- struct packet *next;
- int id;
- uint32_t len;
- // data follows
- } *_packets, **_packets_end;
- void _packet_handler();
- bool recv_ap(nsapi_wifi_ap_t *ap);
-
- char _ip_buffer[16];
- char _gateway_buffer[16];
- char _netmask_buffer[16];
- char _mac_buffer[18];
-};
-
-#endif
--- a/esp8266-driver/ESP8266Interface.cpp Thu Jan 26 14:18:21 2017 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/* ESP8266 implementation of NetworkInterfaceAPI
- * Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include "ESP8266Interface.h"
-
-// Various timeouts for different ESP8266 operations
-#define ESP8266_CONNECT_TIMEOUT 15000
-#define ESP8266_SEND_TIMEOUT 500
-#define ESP8266_RECV_TIMEOUT 0
-#define ESP8266_MISC_TIMEOUT 500
-
-// ESP8266Interface implementation
-ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug)
- : _esp(tx, rx, debug)
-{
- memset(_ids, 0, sizeof(_ids));
- memset(_cbs, 0, sizeof(_cbs));
-
- _esp.attach(this, &ESP8266Interface::event);
-}
-
-int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
- uint8_t channel)
-{
- if (channel != 0) {
- return NSAPI_ERROR_UNSUPPORTED;
- }
-
- set_credentials(ssid, pass, security);
- return connect();
-}
-
-int ESP8266Interface::connect()
-{
- _esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
-
- if (!_esp.startup(3)) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
-
- if (!_esp.dhcp(true, 1)) {
- return NSAPI_ERROR_DHCP_FAILURE;
- }
-
- if (!_esp.connect(ap_ssid, ap_pass)) {
- return NSAPI_ERROR_NO_CONNECTION;
- }
-
- if (!_esp.getIPAddress()) {
- return NSAPI_ERROR_DHCP_FAILURE;
- }
-
- return NSAPI_ERROR_OK;
-}
-
-int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
-{
- memset(ap_ssid, 0, sizeof(ap_ssid));
- strncpy(ap_ssid, ssid, sizeof(ap_ssid));
-
- memset(ap_pass, 0, sizeof(ap_pass));
- strncpy(ap_pass, pass, sizeof(ap_pass));
-
- ap_sec = security;
-
- return 0;
-}
-
-int ESP8266Interface::set_channel(uint8_t channel)
-{
- return NSAPI_ERROR_UNSUPPORTED;
-}
-
-
-int ESP8266Interface::disconnect()
-{
- _esp.setTimeout(ESP8266_MISC_TIMEOUT);
-
- if (!_esp.disconnect()) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
-
- return NSAPI_ERROR_OK;
-}
-
-const char *ESP8266Interface::get_ip_address()
-{
- return _esp.getIPAddress();
-}
-
-const char *ESP8266Interface::get_mac_address()
-{
- return _esp.getMACAddress();
-}
-
-const char *ESP8266Interface::get_gateway()
-{
- return _esp.getGateway();
-}
-
-const char *ESP8266Interface::get_netmask()
-{
- return _esp.getNetmask();
-}
-
-int8_t ESP8266Interface::get_rssi()
-{
- return _esp.getRSSI();
-}
-
-int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count)
-{
- return _esp.scan(res, count);
-}
-
-struct esp8266_socket {
- int id;
- nsapi_protocol_t proto;
- bool connected;
- SocketAddress addr;
-};
-
-int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
-{
- // Look for an unused socket
- int id = -1;
-
- for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
- if (!_ids[i]) {
- id = i;
- _ids[i] = true;
- break;
- }
- }
-
- if (id == -1) {
- return NSAPI_ERROR_NO_SOCKET;
- }
-
- struct esp8266_socket *socket = new struct esp8266_socket;
- if (!socket) {
- return NSAPI_ERROR_NO_SOCKET;
- }
-
- socket->id = id;
- socket->proto = proto;
- socket->connected = false;
- *handle = socket;
- return 0;
-}
-
-int ESP8266Interface::socket_close(void *handle)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- int err = 0;
- _esp.setTimeout(ESP8266_MISC_TIMEOUT);
-
- if (!_esp.close(socket->id)) {
- err = NSAPI_ERROR_DEVICE_ERROR;
- }
-
- _ids[socket->id] = false;
- delete socket;
- return err;
-}
-
-int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
-{
- return NSAPI_ERROR_UNSUPPORTED;
-}
-
-int ESP8266Interface::socket_listen(void *handle, int backlog)
-{
- return NSAPI_ERROR_UNSUPPORTED;
-}
-
-int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- _esp.setTimeout(ESP8266_MISC_TIMEOUT);
-
- const char *proto = (socket->proto == NSAPI_UDP) ? "UDP" : "TCP";
- if (!_esp.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
-
- socket->connected = true;
- return 0;
-}
-
-int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
-{
- return NSAPI_ERROR_UNSUPPORTED;
-}
-
-int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- _esp.setTimeout(ESP8266_SEND_TIMEOUT);
-
- if (!_esp.send(socket->id, data, size)) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
-
- return size;
-}
-
-int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- _esp.setTimeout(ESP8266_RECV_TIMEOUT);
-
- int32_t recv = _esp.recv(socket->id, data, size);
- if (recv < 0) {
- return NSAPI_ERROR_WOULD_BLOCK;
- }
-
- return recv;
-}
-
-int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
-
- if (socket->connected && socket->addr != addr) {
- _esp.setTimeout(ESP8266_MISC_TIMEOUT);
- if (!_esp.close(socket->id)) {
- return NSAPI_ERROR_DEVICE_ERROR;
- }
- socket->connected = false;
- }
-
- if (!socket->connected) {
- int err = socket_connect(socket, addr);
- if (err < 0) {
- return err;
- }
- socket->addr = addr;
- }
-
- return socket_send(socket, data, size);
-}
-
-int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- int ret = socket_recv(socket, data, size);
- if (ret >= 0 && addr) {
- *addr = socket->addr;
- }
-
- return ret;
-}
-
-void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
-{
- struct esp8266_socket *socket = (struct esp8266_socket *)handle;
- _cbs[socket->id].callback = callback;
- _cbs[socket->id].data = data;
-}
-
-void ESP8266Interface::event() {
- for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
- if (_cbs[i].callback) {
- _cbs[i].callback(_cbs[i].data);
- }
- }
-}
--- a/esp8266-driver/ESP8266Interface.h Thu Jan 26 14:18:21 2017 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,275 +0,0 @@
-/* ESP8266 implementation of NetworkInterfaceAPI
- * Copyright (c) 2015 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ESP8266_INTERFACE_H
-#define ESP8266_INTERFACE_H
-
-#include "mbed.h"
-#include "ESP8266.h"
-
-
-#define ESP8266_SOCKET_COUNT 5
-
-/** ESP8266Interface class
- * Implementation of the NetworkStack for the ESP8266
- */
-class ESP8266Interface : public NetworkStack, public WiFiInterface
-{
-public:
- /** ESP8266Interface lifetime
- * @param tx TX pin
- * @param rx RX pin
- * @param debug Enable debugging
- */
- ESP8266Interface(PinName tx, PinName rx, bool debug = false);
-
- /** Start the interface
- *
- * Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
- * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
- *
- * @return 0 on success, negative error code on failure
- */
- virtual int connect();
-
- /** Start the interface
- *
- * Attempts to connect to a WiFi network.
- *
- * @param ssid Name of the network to connect to
- * @param pass Security passphrase to connect to the network
- * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
- * @param channel This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
- * @return 0 on success, or error code on failure
- */
- virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
- uint8_t channel = 0);
-
- /** Set the WiFi network credentials
- *
- * @param ssid Name of the network to connect to
- * @param pass Security passphrase to connect to the network
- * @param security Type of encryption for connection
- * (defaults to NSAPI_SECURITY_NONE)
- * @return 0 on success, or error code on failure
- */
- virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
-
- /** Set the WiFi network channel - NOT SUPPORTED
- *
- * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
- *
- * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0)
- * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED
- */
- virtual int set_channel(uint8_t channel);
-
- /** Stop the interface
- * @return 0 on success, negative on failure
- */
- virtual int disconnect();
-
- /** Get the internally stored IP address
- * @return IP address of the interface or null if not yet connected
- */
- virtual const char *get_ip_address();
-
- /** Get the internally stored MAC address
- * @return MAC address of the interface
- */
- virtual const char *get_mac_address();
-
- /** Get the local gateway
- *
- * @return Null-terminated representation of the local gateway
- * or null if no network mask has been recieved
- */
- virtual const char *get_gateway();
-
- /** Get the local network mask
- *
- * @return Null-terminated representation of the local network mask
- * or null if no network mask has been recieved
- */
- virtual const char *get_netmask();
-
- /** Gets the current radio signal strength for active connection
- *
- * @return Connection strength in dBm (negative value)
- */
- virtual int8_t get_rssi();
-
- /** Scan for available networks
- *
- * This function will block.
- *
- * @param ap Pointer to allocated array to store discovered AP
- * @param count Size of allocated @a res array, or 0 to only count available AP
- * @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
- * @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
- * see @a nsapi_error
- */
- virtual int scan(WiFiAccessPoint *res, unsigned count);
-
- /** Translates a hostname to an IP address with specific version
- *
- * The hostname may be either a domain name or an IP address. If the
- * hostname is an IP address, no network transactions will be performed.
- *
- * If no stack-specific DNS resolution is provided, the hostname
- * will be resolve using a UDP socket on the stack.
- *
- * @param address Destination for the host SocketAddress
- * @param host Hostname to resolve
- * @param version IP version of address to resolve, NSAPI_UNSPEC indicates
- * version is chosen by the stack (defaults to NSAPI_UNSPEC)
- * @return 0 on success, negative error code on failure
- */
- using NetworkInterface::gethostbyname;
-
- /** Add a domain name server to list of servers to query
- *
- * @param addr Destination for the host address
- * @return 0 on success, negative error code on failure
- */
- using NetworkInterface::add_dns_server;
-
-protected:
- /** Open a socket
- * @param handle Handle in which to store new socket
- * @param proto Type of socket to open, NSAPI_TCP or NSAPI_UDP
- * @return 0 on success, negative on failure
- */
- virtual int socket_open(void **handle, nsapi_protocol_t proto);
-
- /** Close the socket
- * @param handle Socket handle
- * @return 0 on success, negative on failure
- * @note On failure, any memory associated with the socket must still
- * be cleaned up
- */
- virtual int socket_close(void *handle);
-
- /** Bind a server socket to a specific port
- * @param handle Socket handle
- * @param address Local address to listen for incoming connections on
- * @return 0 on success, negative on failure.
- */
- virtual int socket_bind(void *handle, const SocketAddress &address);
-
- /** Start listening for incoming connections
- * @param handle Socket handle
- * @param backlog Number of pending connections that can be queued up at any
- * one time [Default: 1]
- * @return 0 on success, negative on failure
- */
- virtual int socket_listen(void *handle, int backlog);
-
- /** Connects this TCP socket to the server
- * @param handle Socket handle
- * @param address SocketAddress to connect to
- * @return 0 on success, negative on failure
- */
- virtual int socket_connect(void *handle, const SocketAddress &address);
-
- /** Accept a new connection.
- * @param handle Handle in which to store new socket
- * @param server Socket handle to server to accept from
- * @return 0 on success, negative on failure
- * @note This call is not-blocking, if this call would block, must
- * immediately return NSAPI_ERROR_WOULD_WAIT
- */
- virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
-
- /** Send data to the remote host
- * @param handle Socket handle
- * @param data The buffer to send to the host
- * @param size The length of the buffer to send
- * @return Number of written bytes on success, negative on failure
- * @note This call is not-blocking, if this call would block, must
- * immediately return NSAPI_ERROR_WOULD_WAIT
- */
- virtual int socket_send(void *handle, const void *data, unsigned size);
-
- /** Receive data from the remote host
- * @param handle Socket handle
- * @param data The buffer in which to store the data received from the host
- * @param size The maximum length of the buffer
- * @return Number of received bytes on success, negative on failure
- * @note This call is not-blocking, if this call would block, must
- * immediately return NSAPI_ERROR_WOULD_WAIT
- */
- virtual int socket_recv(void *handle, void *data, unsigned size);
-
- /** Send a packet to a remote endpoint
- * @param handle Socket handle
- * @param address The remote SocketAddress
- * @param data The packet to be sent
- * @param size The length of the packet to be sent
- * @return The number of written bytes on success, negative on failure
- * @note This call is not-blocking, if this call would block, must
- * immediately return NSAPI_ERROR_WOULD_WAIT
- */
- virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
-
- /** Receive a packet from a remote endpoint
- * @param handle Socket handle
- * @param address Destination for the remote SocketAddress or null
- * @param buffer The buffer for storing the incoming packet data
- * If a packet is too long to fit in the supplied buffer,
- * excess bytes are discarded
- * @param size The length of the buffer
- * @return The number of received bytes on success, negative on failure
- * @note This call is not-blocking, if this call would block, must
- * immediately return NSAPI_ERROR_WOULD_WAIT
- */
- virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
-
- /** Register a callback on state change of the socket
- * @param handle Socket handle
- * @param callback Function to call on state change
- * @param data Argument to pass to callback
- * @note Callback may be called in an interrupt context.
- */
- virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
-
- /** Provide access to the NetworkStack object
- *
- * @return The underlying NetworkStack object
- */
- virtual NetworkStack *get_stack()
- {
- return this;
- }
-
-private:
- ESP8266 _esp;
- bool _ids[ESP8266_SOCKET_COUNT];
-
- char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
- nsapi_security_t ap_sec;
- uint8_t ap_ch;
- char ap_pass[64]; /* The longest allowed passphrase */
-
- void event();
-
- struct {
- void (*callback)(void *);
- void *data;
- } _cbs[ESP8266_SOCKET_COUNT];
-};
-
-#endif
--- a/esp8266-driver/README.md Thu Jan 26 14:18:21 2017 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -# esp8266 mbed-os driver -The driver for the ESP8266 WiFi module - -## Firmware version -esp8266 modules come in different shapes and forms, but most important difference is which firmware version it is programmed with. To make sure that your module has mbed-os compatible firmware follow update guide: https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update
--- a/main.cpp Thu Jan 26 14:18:21 2017 -0600
+++ b/main.cpp Thu Jan 26 16:55:23 2017 -0600
@@ -40,7 +40,7 @@
#include "Masters/DS2465/DS2465.h"
#include "Display.hpp"
#include "RomId/RomId.h"
-#include "ESP8266Interface.h"
+#include "ESP8266.hpp"
#include "mbed.h"
using OneWire::RomId;
@@ -77,9 +77,6 @@
static const Display::Color Purple = { 0x6E, 0x25, 0x85 };
/// @}
-static const char wifiSsid[] = "TWS iPhone";
-static const char wifiPassword[] = "maxim1234";
-
/// @{
/// Peripheral and pin definitions
static Serial pc(USBTX, USBRX);
@@ -91,9 +88,7 @@
static Display lcd(i2c, 0x78, 0x98);
static DS2465 ds2465(i2c, 0x30);
static SensorNode sensorNode(i2c, 0x90, 0x94, ds2465);
-static ESP8266Interface esp8266(D1, D0, true);
-static DigitalOut esp8266_RST(D2, 0);
-static DigitalOut esp8266_CH_PD(D3, 1);
+static ESP8266 esp8266(D1, D0, D2, D3, 38400);
static WebServerInterface webIntf(esp8266);
/// @}
@@ -138,8 +133,7 @@
displayStatus(currentStatus);
// Connect to Wifi network
- esp8266_RST = 1;
- result = (esp8266.connect(wifiSsid, wifiPassword, NSAPI_SECURITY_WPA2) == 0);
+ result = webIntf.initialize();
// Read session ID
if (result)
--- a/mbed-os.lib Thu Jan 26 14:18:21 2017 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://github.com/ARMmbed/mbed-os/#34c1facf42a174f47fdf9002cd8c6bf10ac41744 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Jan 26 16:55:23 2017 -0600 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/2e9cc70d1897 \ No newline at end of file
MAXREFDES143#: DeepCover Embedded Security in IoT Authenticated Sensing & Notification