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.

Files at this revision

API Documentation at this revision

Comitter:
IanBenzMaxim
Date:
Thu Jan 26 14:18:21 2017 -0600
Parent:
27:81a87d29bedd
Child:
29:590a7561318b
Commit message:
Migrated the web interface to the mbed 5 networking stack to improve system compatibility.

Changed in this revision

ESP8266.cpp Show diff for this revision Revisions of this file
ESP8266.hpp Show diff for this revision Revisions of this file
WebServerInterface.cpp Show annotated file Show diff for this revision Revisions of this file
WebServerInterface.hpp Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/ESP8266/ATParser.lib Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/ESP8266/ESP8266.cpp Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/ESP8266/ESP8266.h Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/ESP8266Interface.cpp Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/ESP8266Interface.h Show annotated file Show diff for this revision Revisions of this file
esp8266-driver/README.md Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os-mutex.lib Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
--- a/ESP8266.cpp	Fri Dec 16 20:14:05 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,489 +0,0 @@
-/*******************************************************************************
-* 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
--- a/ESP8266.hpp	Fri Dec 16 20:14:05 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*******************************************************************************
-* 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	Fri Dec 16 20:14:05 2016 +0000
+++ b/WebServerInterface.cpp	Thu Jan 26 14:18:21 2017 -0600
@@ -31,9 +31,11 @@
 *******************************************************************************
 */
 
+#include <sstream>
 #include <vector>
 #include "WebServerInterface.hpp"
-#include "ESP8266.hpp"
+#include "NetworkStack.h"
+#include "TCPSocket.h"
 #include "Slaves/Authenticators/ISha256MacCoproc.h"
 #include "SensorData.hpp"
 #include "HexConversions.hpp"
@@ -42,8 +44,6 @@
 
 using OneWire::ISha256MacCoproc;
 
-const char WebServerInterface::wifiSsid[] = "WifiSsid";
-const char WebServerInterface::wifiPassword[] = "WifiPassword";
 const char WebServerInterface::serverAddress[] = "www.mxim-security.us";
 const unsigned int WebServerInterface::serverPort = 80;
 const char WebServerInterface::serverPostPath[] = "/post.php";
@@ -71,32 +71,6 @@
   return (MacCoproc.computeSlaveSecret(fillData, fillData, secretData) == ISha256MacCoproc::Success);
 }
 
-WebServerInterface::WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc)
-  : esp8266(esp8266), pc(pc)
-{
-  
-}
-
-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.
@@ -241,13 +215,7 @@
 
 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)
   {
@@ -257,60 +225,47 @@
   }
   
   // Open connection
-  esp8266.clearRecvData(); // Clear received data buffer
-  result = (esp8266.openConnection(ESP8266::TCP, serverAddress, 80) == ESP8266::AT_OK);
+  TCPSocket socket(&networkStack);
+  result = (socket.connect(serverAddress, 80) == 0);
   if (result)
   {
     // Request challenge
-    result = (esp8266.sendData(formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString)) == ESP8266::AT_OK);
+    std::string httpData = formatHttpGet(serverAddress, serverChallengePath, m_sessionIdString);
+    result = (socket.send(httpData.data(), httpData.size()) == httpData.size());
     if (result)
     {
       // Receive server response
-      for (int i = 0; i < 10; i++)
-      {
-        while (esp8266.recvIpDataReadable())
+      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()))
         {
-          char read = esp8266.getcRecvIpData();
-          if (pc != NULL)
-            pc->putc(read);
-          if (response.length() < response.capacity())
+          uint8_t challenge[challengeLen];
+          challengePos += challengeSearch.length();
+          for (size_t i = 0; i < challengeLen; i++)
           {
-            response += read;
+            std::sscanf(httpData.substr(challengePos + (i * charsPerByte), charsPerByte).c_str(), "%2hhx", &challenge[i]);
           }
-          else
+          
+          // Post sensor data
+          httpData = formatHttpPost(serverAddress, serverPostPath, m_sessionIdString, macCoproc, event, postData, challenge);
+          result = (socket.send(httpData.data(), httpData.size()) == httpData.size());
+          if (result)
           {
-            wait_ms(ESP8266::sendDataRecoveryTimeMs); // Wait for ESP8266 specified recovery time
-            goto close_get_connection;
+              result = (socket.recv(recvBuf, sizeof(recvBuf) / sizeof(recvBuf[0])) >= 0);
           }
         }
-        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
-    esp8266.closeConnection();
+    socket.close();
   }
   
   return result;
--- a/WebServerInterface.hpp	Fri Dec 16 20:14:05 2016 +0000
+++ b/WebServerInterface.hpp	Thu Jan 26 14:18:21 2017 -0600
@@ -46,7 +46,7 @@
 
 namespace mbed { class Serial; }
 namespace OneWire { class ISha256MacCoproc; }
-class ESP8266;
+class NetworkStack;
 struct SensorData;
 
 /// Network interface to the web server supporting authenticated posting of event
@@ -56,11 +56,7 @@
 public:  
   /// @param esp8266 Interface to ESP8266 for Wi-Fi access.
   /// @param pc Optional serial interface for received web traffic.
-  WebServerInterface(ESP8266 & esp8266, mbed::Serial * pc = NULL);
-  
-  /// Initialize network interface and connect to access point.
-  /// @returns True on success.
-  bool initialize();
+  WebServerInterface(NetworkStack & networkStack) : networkStack(networkStack) { }
   
   /// Send an authenticated event message to the web server.
   /// @param macCoProc Coprocessor such as the DS2465 used to calculate the authentication MAC.
@@ -85,8 +81,6 @@
 private:
   /// @{
   /// Configuration strings.
-  static const char wifiSsid[];
-  static const char wifiPassword[];
   static const char serverAddress[];
   static const unsigned int serverPort;
   static const char serverPostPath[];
@@ -96,8 +90,9 @@
   OneWire::RomId m_sessionId;
   std::string m_sessionIdString;
   
-  ESP8266 & esp8266;
-  mbed::Serial * pc;
+  NetworkStack & networkStack;
+  
+  char recvBuf[1024];
 };
 
 #endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/ESP8266/ATParser.lib	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/ATParser/#269f14532b98442669c50383782cbce1c67aced5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/ESP8266/ESP8266.cpp	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,302 @@
+/* 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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/ESP8266/ESP8266.h	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,213 @@
+/* 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/ESP8266Interface.cpp	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,282 @@
+/* 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);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/ESP8266Interface.h	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,275 @@
+/* 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/esp8266-driver/README.md	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,5 @@
+# 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	Fri Dec 16 20:14:05 2016 +0000
+++ b/main.cpp	Thu Jan 26 14:18:21 2017 -0600
@@ -40,7 +40,7 @@
 #include "Masters/DS2465/DS2465.h"
 #include "Display.hpp"
 #include "RomId/RomId.h"
-#include "ESP8266.hpp"
+#include "ESP8266Interface.h"
 #include "mbed.h"
 
 using OneWire::RomId;
@@ -77,6 +77,9 @@
 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);
@@ -88,8 +91,10 @@
 static Display lcd(i2c, 0x78, 0x98);
 static DS2465 ds2465(i2c, 0x30);
 static SensorNode sensorNode(i2c, 0x90, 0x94, ds2465);
-static ESP8266 esp8266(D1, D0, D2, D3, 38400);
-static WebServerInterface webIntf(esp8266, &pc);
+static ESP8266Interface esp8266(D1, D0, true);
+static DigitalOut esp8266_RST(D2, 0);
+static DigitalOut esp8266_CH_PD(D3, 1);
+static WebServerInterface webIntf(esp8266);
 /// @}
 
 static bool useInvalidSecret = false; ///< Imitate an invalid controller when posting to web server.
@@ -133,7 +138,8 @@
       displayStatus(currentStatus);
       
       // Connect to Wifi network
-      result = webIntf.initialize();
+      esp8266_RST = 1;
+      result = (esp8266.connect(wifiSsid, wifiPassword, NSAPI_SECURITY_WPA2) == 0);
       
       // Read session ID
       if (result)
--- a/mbed-os-mutex.lib	Fri Dec 16 20:14:05 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://developer.mbed.org/users/IanBenzMaxim/code/mbed-os-mutex/#ff111f3941b4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu Jan 26 14:18:21 2017 -0600
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#34c1facf42a174f47fdf9002cd8c6bf10ac41744
\ No newline at end of file