Example of AWS IoT connection and Web Dashboard thru STM32 Nucleo evaluation board and mbed OS.

Dependencies:   X_NUCLEO_IKS01A1 mbed FP MQTTPacket DnsQuery ATParser

Introduction

The demo is aimed to STM32 Nucleo board with WiFi and sensors expansions. The board is a "thing" for the AWS IoT service. It updates IoT service shadow with sensors data every second and checks subscription messages.

Hardware Configuration

https://github.com/Klika-Tech/nucleo-aws-iot-demo/raw/master/doc/assets/device.jpg

Software Configuration

  • Import this Project to mbed online compiler
  • Find the next part of code in main.cpp file ...

WiFi network credential

#include "mbed.h"
// WiFi network credential
#define SSID   ""  // Network must be visible otherwise it can't connect
#define PASSW  ""
#error "Wifi SSID & password empty"
  • ... And set it to your Network Name and Password. Do not forget to remove "#error" pragma line.

Information

Nucleo WiFi module is not the same as your smartphone or laptope - it is based on demo board. To avoid connection problems:

  1. Place Nucleo as close to WiFi hot spot as possible. Or...
  2. Turn on mobile hot spot in your laptop as close to the device as possible.
  3. Make sure that hot spot permits 2.4 GHz band communications
  • Setup BackEnd and store certificates using this backend setup instruction
  • Find AWS_IOT_MQTT_HOST define and change it to HTTPS point mentioned in your AWS IoT thing properties named "interact"

#define AWS_IOT_MQTT_HOST              "xxxxxxxxxx.iot.us-east-1.amazonaws.com" //Use your own host.
  • Find the certificate defines clientCRT and clientKey in main.cpp file and change it to ones provided by Amazon.

/**********************************************************************************************
***********************************************************************************************
				Device Identity Certificates: Modify for your AWS IoT Thing
***********************************************************************************************
***********************************************************************************************/

/****************************************
(somecode)-certificate.pem.crt - Amazon signed PEM sertificate.
*****************************************/

//This Client cert is example. Use own instead.
const uint8_t clientCRT[] = "\
-----BEGIN CERTIFICATE-----\n\
MIIDBjCCAe6gAwIBAgIUVph856omeIxW3UPioq+UrX1DbwowDQYJKoZIhvcNAQEL\
BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\
SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTE3MDUyNTExNTEy\
OVoXDTQ5MTIzMTIzNTk1OVowgZUxCzAJBgNVBAYTAkJZMQ4wDAYDVQQIDAVNaW5z\
azEOMAwGA1UEBwwFTWluc2sxFzAVBgNVBAoMDktsaWthLVRlY2ggTExDMRcwFQYD\
VQQLDA5LbGlrYS1UZWNoIExMQzEMMAoGA1UEAwwDUm5EMSYwJAYJKoZIhvcNAQkB\
FhdtdmF0YWxldUBrbGlrYS10ZWNoLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH\
A0IABCJgOQJmoTBJVPfli9Hm/JVixaxkY5rtlgrYO3hSl633A2hg0P/ue0wXDbF3\
aQ0X57IRFE4k4FEbr3UXjT/IczKjYDBeMB8GA1UdIwQYMBaAFK3YzTUPlYB2Li75\
i/z8rEogr1d6MB0GA1UdDgQWBBT18HXBaXFJuAR/0SwegnxJ+pyJ6TAMBgNVHRMB\
Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAb0Ux1aH5\
RLxjrfGqXN6rPVqh8QQRS+AyBfzmaQN8HaPZMkX5WxXLvcn0A3uWlwQxPPkcZ4zf\
51GHtFFQWB4YZ8dx8mUQ0v/j7onHjCJgZ8iDgwOyKMGtnsDZWCakQw+a6cj+NrMZ\
tzhjwCzEEP6ePcbXwErI5OOzLuWns2L/JEr2wWNkokgRuS8ewr/SQ9OLWIWa2rFM\
ahPNTb3y/qBeWdjeJmhI+TOxdqIpsF8roWP25zwo/zkzCHCjXFBrL+0CA4MpxIl9\
x02i7aAhlJ6ys80lDxdeWeeQJXRKkGknP8mcmKn3iEqqJ5s1dQePj2b5d3ldatya\
wsxQBqqZXzIWEw==\
\n\
-----END CERTIFICATE-----\n";



/**********************************************************************************************
***********************************************************************************************
						Private Key: Modify for your AWS IoT Thing
***********************************************************************************************
***********************************************************************************************/

/********************************************************************8****************************************
nucleo.key.pem - client key generated according to readme.
**************************************************************************************************************/

//This Client Key is example. Use own instead.
const uint8_t clientKey[] ="\
-----BEGIN EC PARAMETERS-----\n\
BggqhkjOPQMBBw==\
-----END EC PARAMETERS-----\n\
-----BEGIN EC PRIVATE KEY-----\n\
MHcCAQEEIHPRfWSC8/k/BsqDWKuP15dXsI9fGwpkTIsLZe6mIrAAoAoGCCqGSM49\
AwEHoUQDQgAEImA5AmahMElU9+WL0eb8lWLFrGRjmu2WCtg7eFKXrfcDaGDQ/+57\
TBcNsXdpDRfnshEUTiTgURuvdReNP8hzMg==\
-----END EC PRIVATE KEY-----\n";

Build and Check

  1. Plugin your board to USB of your PC. USB Disk Drive and USB COM Port should appear in your system.
  2. Open any Serial Console, connect it to your USB Serial Port and setup speed equal to 115200.
  3. Compile this Project and save .bin file to USB Disk Drive
  4. After board reset you should see next log in serial console:

X-NUCLEO-IDW01M1 mbed Application

connecting to AP
LOG:   int main() L#361 Connected to WiFI.
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#186 =====================================
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#187 Connecting WiFi.
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#188 Nucleo IP ADDRESS: X.X.X.X
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#189 Nucleo MAC ADDRESS: 00:11:22:33:44:55
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#190 Server Hostname: xxxxxxxx.iot.us-east-1.amazonaws.com port: 8883
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#191 Client ID: Nucleo
LOG:   int connect(MQTT::Client<MQTTWiFi, Countdown, 350, 5> *, MQTTWiFi *) L#194 =====================================
LOG:   int MQTTSocket::getNTPtime(int) L#58 Success receiving time from ntp server. Tick from 1 Jan 1970 is equal to 1505399292.
--->TCP Connected
--->MQTT Connected
--->>>MQTT subscribed to: Nucleo/test
Length - 245, Publishing {"state": {"reported": {"temperature": 23.690001, "humidity": 98.190002, "pressure": 982.869141, "accelerometer": [-0.009000, 0.030000, 0.971000], "gyroscope": [0.420000, -2.660000, 1.750000], "magnetometer": [-3.600000, -7.100000, 53.300000]}}}
Length - 245, Publishing {"state": {"reported": {"temperature": 23.660000, "humidity": 98.010002, "pressure": 982.770264, "accelerometer": [-0.009000, 0.030000, 0.971000], "gyroscope": [0.770000, -2.310000, 1.470000], "magnetometer": [-3.100000, -8.300000, 54.200000]}}}
Length - 245, Publishing {"state": {"reported": {"temperature": 23.670000, "humidity": 98.129997, "pressure": 982.724121, "accelerometer": [-0.008000, 0.029000, 0.971000], "gyroscope": [0.630000, -2.380000, 1.400000], "magnetometer": [-3.100000, -7.900000, 53.400000]}}}
Length - 245, Publishing {"state": {"reported": {"temperature": 23.690001, "humidity": 98.019997, "pressure": 982.840088, "accelerometer": [-0.009000, 0.030000, 0.972000], "gyroscope": [0.700000, -2.450000, 1.540000], "magnetometer": [-3.700000, -7.900000, 53.400000]}}}
Length - 245, Publishing {"state": {"reported": {"temperature": 23.709999, "humidity": 98.040001, "pressure": 982.828613, "accelerometer": [-0.009000, 0.030000, 0.971000], "gyroscope": [0.630000, -2.520000, 1.470000], "magnetometer": [-2.900000, -7.400000, 52.400000]}}}
Length - 245, Publishing {"state": {"reported": {"temperature": 23.719999, "humidity": 97.860001, "pressure": 982.917236, "accelerometer": [-0.026000, 0.103000, 0.891000], "gyroscope": [1.050000, -2.310000, 1.260000], "magnetometer": [-3.300000, -7.100000, 53.500000]}}}

Information

Device connection state might be checked by Green Led on the board. Green light means that device is connected and transferring data to cloud.

  1. Configure and start your dashboard using instruction and corresponding sources from github
  2. Use Blue button to set up markers to charts.
  3. Use AWS IoT console MQTT Client to test device subscription to "Nucleo/test". Just publish any message to this topic and serial port output.
  4. PROFIT!

Files at this revision

API Documentation at this revision

Comitter:
PavelSavyhin
Date:
Wed Sep 27 14:40:52 2017 +0300
Child:
1:042ca9148926
Commit message:
Initial commit

Changed in this revision

MQTT/FP.lib Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTAsync.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTClient.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTEthernet.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTLogging.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTPacket.lib Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTSocket.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTWiFi.h Show annotated file Show diff for this revision Revisions of this file
MQTT/MQTTmbed.h Show annotated file Show diff for this revision Revisions of this file
MQTT/NOTICE.TXT Show annotated file Show diff for this revision Revisions of this file
NOTICE.txt Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/CellularInterface.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/DnsQuery.lib Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/EthernetInterface.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/MeshInterface.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/NOTICE.txt Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/NetworkStack.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/NetworkStack.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/Socket.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/SocketAddress.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/SocketAddress.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/TCPServer.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/TCPServer.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/TCPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/TCPSocket.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/UDPSocket.h Show annotated file Show diff for this revision Revisions of this file
NetworkSocketAPI/WiFiInterface.h Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/NOTICE.txt Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SPWF01SA/ATParser.lib Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SPWF01SA/NOTICE.txt Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SPWF01SA/SPWFSA01.cpp Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SPWF01SA/SPWFSA01.h Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SpwfInterface.cpp Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IDW01M1v2/SpwfInterface.h Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IKS01A1.lib 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.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/FP.lib	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+http://mbed.org/users/sam_grove/code/FP/#3c62ba1807ac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTAsync.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,607 @@
+/*******************************************************************************
+ * Copyright (c) 2014 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+#if !defined(MQTTASYNC_H)
+#define MQTTASYNC_H
+
+#include "FP.h"
+#include "MQTTPacket.h"
+#include "stdio.h"
+
+namespace MQTT
+{
+
+
+enum QoS { QOS0, QOS1, QOS2 };
+
+
+struct Message
+{
+    enum QoS qos;
+    bool retained;
+    bool dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+};
+
+
+class PacketId
+{
+public:
+    PacketId();
+    
+    int getNext();
+   
+private:
+    static const int MAX_PACKET_ID = 65535;
+    int next;
+};
+
+typedef void (*messageHandler)(Message*);
+
+typedef struct limits
+{
+	int MAX_MQTT_PACKET_SIZE; // 
+	int MAX_MESSAGE_HANDLERS;  // each subscription requires a message handler
+	int MAX_CONCURRENT_OPERATIONS;  // each command which runs concurrently can have a result handler, when we are in multi-threaded mode
+	int command_timeout_ms;
+		
+	limits()
+	{
+		MAX_MQTT_PACKET_SIZE = 100;
+		MAX_MESSAGE_HANDLERS = 5;
+		MAX_CONCURRENT_OPERATIONS = 1; // 1 indicates single-threaded mode - set to >1 for multithreaded mode
+		command_timeout_ms = 30000;
+	}
+} Limits;
+  
+
+/**
+ * @class Async
+ * @brief non-blocking, threaded MQTT client API
+ * @param Network a network class which supports send, receive
+ * @param Timer a timer class with the methods: 
+ */ 
+template<class Network, class Timer, class Thread, class Mutex> class Async
+{
+    
+public:    
+
+	struct Result
+	{
+    	/* success or failure result data */
+    	Async<Network, Timer, Thread, Mutex>* client;
+		int rc;
+	};
+
+	typedef void (*resultHandler)(Result*);	
+   
+    Async(Network* network, const Limits limits = Limits()); 
+        
+    typedef struct
+    {
+        Async* client;
+        Network* network;
+    } connectionLostInfo;
+    
+    typedef int (*connectionLostHandlers)(connectionLostInfo*);
+    
+    /** Set the connection lost callback - called whenever the connection is lost and we should be connected
+     *  @param clh - pointer to the callback function
+     */
+    void setConnectionLostHandler(connectionLostHandlers clh)
+    {
+        connectionLostHandler.attach(clh);
+    }
+    
+    /** Set the default message handling callback - used for any message which does not match a subscription message handler
+     *  @param mh - pointer to the callback function
+     */
+    void setDefaultMessageHandler(messageHandler mh)
+    {
+        defaultMessageHandler.attach(mh);
+    }
+           
+    int connect(resultHandler fn, MQTTPacket_connectData* options = 0);
+    
+     template<class T>
+    int connect(void(T::*method)(Result *), MQTTPacket_connectData* options = 0, T *item = 0);  // alternative to pass in pointer to member function
+        
+    int publish(resultHandler rh, const char* topic, Message* message);
+    
+    int subscribe(resultHandler rh, const char* topicFilter, enum QoS qos, messageHandler mh);
+    
+    int unsubscribe(resultHandler rh, const char* topicFilter);
+    
+    int disconnect(resultHandler rh);
+    
+private:
+
+    void run(void const *argument);
+    int cycle(int timeout);
+    int waitfor(int packet_type, Timer& atimer);
+	int keepalive();
+	int findFreeOperation();
+
+    int decodePacket(int* value, int timeout);
+    int readPacket(int timeout);
+    int sendPacket(int length, int timeout);
+	int deliverMessage(MQTTString* topic, Message* message);
+    
+    Thread* thread;
+    Network* ipstack;
+    
+    Limits limits;
+    
+    char* buf;  
+    char* readbuf;
+
+    Timer ping_timer, connect_timer;
+    unsigned int keepAliveInterval;
+	bool ping_outstanding;
+    
+    PacketId packetid;
+    
+    typedef FP<void, Result*> resultHandlerFP;    
+    resultHandlerFP connectHandler; 
+    
+    typedef FP<void, Message*> messageHandlerFP;
+    struct MessageHandlers
+    {
+    	const char* topic;
+    	messageHandlerFP fp;
+    } *messageHandlers;      // Message handlers are indexed by subscription topic
+    
+    // how many concurrent operations should we allow?  Each one will require a function pointer
+    struct Operations
+    {
+    	unsigned short id;
+    	resultHandlerFP fp;
+    	const char* topic;         // if this is a publish, store topic name in case republishing is required
+    	Message* message;    // for publish, 
+    	Timer timer;         // to check if the command has timed out
+    } *operations;           // result handlers are indexed by packet ids
+
+	static void threadfn(void* arg);
+	
+	messageHandlerFP defaultMessageHandler;
+    
+    typedef FP<int, connectionLostInfo*> connectionLostFP;
+    
+    connectionLostFP connectionLostHandler;
+    
+};
+
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> void MQTT::Async<Network, Timer, Thread, Mutex>::threadfn(void* arg)
+{
+    ((Async<Network, Timer, Thread, Mutex>*) arg)->run(NULL);
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> MQTT::Async<Network, Timer, Thread, Mutex>::Async(Network* network, Limits limits)  : limits(limits), packetid()
+{
+	this->thread = 0;
+	this->ipstack = network;
+	this->ping_timer = Timer();
+	this->ping_outstanding = 0;
+	   
+	// How to make these memory allocations portable?  I was hoping to avoid the heap
+	buf = new char[limits.MAX_MQTT_PACKET_SIZE];
+	readbuf = new char[limits.MAX_MQTT_PACKET_SIZE];
+	this->operations = new struct Operations[limits.MAX_CONCURRENT_OPERATIONS];
+	for (int i = 0; i < limits.MAX_CONCURRENT_OPERATIONS; ++i)
+		operations[i].id = 0;
+	this->messageHandlers = new struct MessageHandlers[limits.MAX_MESSAGE_HANDLERS];
+	for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
+		messageHandlers[i].topic = 0;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::sendPacket(int length, int timeout)
+{
+    int sent = 0;
+    
+    while (sent < length)
+        sent += ipstack->write(&buf[sent], length, timeout);
+	if (sent == length)
+	    ping_timer.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet    
+    return sent;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::decodePacket(int* value, int timeout)
+{
+    char c;
+    int multiplier = 1;
+    int len = 0;
+	const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        int rc = MQTTPACKET_READ_ERROR;
+
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        rc = ipstack->read(&c, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (c & 127) * multiplier;
+        multiplier *= 128;
+    } while ((c & 128) != 0);
+exit:
+    return len;
+}
+
+
+/**
+ * If any read fails in this method, then we should disconnect from the network, as on reconnect
+ * the packets can be retried. 
+ * @param timeout the max time to wait for the packet read to complete, in milliseconds
+ * @return the MQTT packet type, or -1 if none
+ */
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::readPacket(int timeout) 
+{
+    int rc = -1;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    if (ipstack->read(readbuf, 1, timeout) != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    decodePacket(&rem_len, timeout);
+    len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length back into the buffer */
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (ipstack->read(readbuf + len, rem_len, timeout) != rem_len)
+        goto exit;
+
+    header.byte = readbuf[0];
+    rc = header.bits.type;
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::deliverMessage(MQTTString* topic, Message* message)
+{
+	int rc = -1;
+
+	// we have to find the right message handler - indexed by topic
+	for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
+	{
+		if (messageHandlers[i].topic != 0 && MQTTPacket_equals(topic, (char*)messageHandlers[i].topic))
+		{
+			messageHandlers[i].fp(message);
+			rc = 0;
+			break;
+		}
+	}
+	
+	return rc;
+}
+
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::cycle(int timeout)
+{
+    /* get one piece of work off the wire and one pass through */
+
+    // read the socket, see what work is due
+    int packet_type = readPacket(timeout);
+    
+	int len, rc;
+    switch (packet_type)
+    {
+        case CONNACK:
+			if (this->thread)
+			{
+				Result res = {this, 0};
+            	if (MQTTDeserialize_connack(&res.rc, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+                	;
+				connectHandler(&res);
+				connectHandler.detach(); // only invoke the callback once
+			}
+			break;
+        case PUBACK:
+        	if (this->thread)
+        		; //call resultHandler
+        case SUBACK:
+            break;
+        case PUBLISH:
+			MQTTString topicName;
+			Message msg;
+			rc = MQTTDeserialize_publish((int*)&msg.dup, (int*)&msg.qos, (int*)&msg.retained, (int*)&msg.id, &topicName,
+								 (char**)&msg.payload, (int*)&msg.payloadlen, readbuf, limits.MAX_MQTT_PACKET_SIZE);;
+			if (msg.qos == QOS0)
+				deliverMessage(&topicName, &msg);
+            break;
+        case PUBREC:
+   	        int type, dup, mypacketid;
+   	        if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+   	            ; 
+   	        // must lock this access against the application thread, if we are multi-threaded
+			len = MQTTSerialize_ack(buf, limits.MAX_MQTT_PACKET_SIZE, PUBREL, 0, mypacketid);
+		    rc = sendPacket(len, timeout); // send the PUBREL packet
+			if (rc != len) 
+				goto exit; // there was a problem
+
+            break;
+        case PUBCOMP:
+            break;
+        case PINGRESP:
+			ping_outstanding = false;
+            break;
+    }
+	keepalive();
+exit:
+    return packet_type;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::keepalive()
+{
+	int rc = 0;
+
+	if (keepAliveInterval == 0)
+		goto exit;
+
+	if (ping_timer.expired())
+	{
+		if (ping_outstanding)
+			rc = -1;
+		else
+		{
+			int len = MQTTSerialize_pingreq(buf, limits.MAX_MQTT_PACKET_SIZE);
+			rc = sendPacket(len, 1000); // send the ping packet
+			if (rc != len) 
+				rc = -1; // indicate there's a problem
+			else
+				ping_outstanding = true;
+		}
+	}
+
+exit:
+	return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> void MQTT::Async<Network, Timer, Thread, Mutex>::run(void const *argument)
+{
+	while (true)
+		cycle(ping_timer.left_ms());
+}
+
+
+// only used in single-threaded mode where one command at a time is in process
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::waitfor(int packet_type, Timer& atimer)
+{
+	int rc = -1;
+	
+	do
+    {
+		if (atimer.expired()) 
+			break; // we timed out
+	}
+	while ((rc = cycle(atimer.left_ms())) != packet_type);	
+	
+	return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::connect(resultHandler resultHandler, MQTTPacket_connectData* options)
+{
+	connect_timer.countdown(limits.command_timeout_ms);
+
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    if (options == 0)
+        options = &default_options; // set default options if none were supplied
+    
+    this->keepAliveInterval = options->keepAliveInterval;
+	ping_timer.countdown(this->keepAliveInterval);
+    int len = MQTTSerialize_connect(buf, limits.MAX_MQTT_PACKET_SIZE, options);
+    int rc = sendPacket(len, connect_timer.left_ms()); // send the connect packet
+	if (rc != len) 
+		goto exit; // there was a problem
+    
+    if (resultHandler == 0)     // wait until the connack is received 
+    {
+        // this will be a blocking call, wait for the connack
+		if (waitfor(CONNACK, connect_timer) == CONNACK)
+		{
+        	int connack_rc = -1;
+        	if (MQTTDeserialize_connack(&connack_rc, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+	        	rc = connack_rc;
+	    }
+    }
+    else
+    {
+        // set connect response callback function
+        connectHandler.attach(resultHandler);
+        
+        // start background thread            
+        this->thread = new Thread((void (*)(void const *argument))&MQTT::Async<Network, Timer, Thread, Mutex>::threadfn, (void*)this);
+    }
+    
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::findFreeOperation()
+{
+	int found = -1;
+	for (int i = 0; i < limits.MAX_CONCURRENT_OPERATIONS; ++i)
+	{
+		if (operations[i].id == 0)
+		{
+			found = i;
+			break;
+		}
+	}
+	return found;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::subscribe(resultHandler resultHandler, const char* topicFilter, enum QoS qos, messageHandler messageHandler)
+{
+	int index = 0;
+	if (this->thread)
+		index = findFreeOperation();	
+	Timer& atimer = operations[index].timer;
+	
+	atimer.countdown(limits.command_timeout_ms);
+    MQTTString topic = {(char*)topicFilter, 0, 0};
+    
+    int len = MQTTSerialize_subscribe(buf, limits.MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
+    int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
+	if (rc != len) 
+		goto exit; // there was a problem
+    
+    /* wait for suback */
+    if (resultHandler == 0)
+    {
+        // this will block
+        if (waitfor(SUBACK, atimer) == SUBACK)
+        {
+            int count = 0, grantedQoS = -1, mypacketid;
+            if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+                rc = grantedQoS; // 0, 1, 2 or 0x80 
+            if (rc != 0x80)
+            {
+            	for (int i = 0; i < limits.MAX_MESSAGE_HANDLERS; ++i)
+				{
+					if (messageHandlers[i].topic == 0)
+					{
+						messageHandlers[i].topic = topicFilter;
+						messageHandlers[i].fp.attach(messageHandler);
+						rc = 0;
+						break;
+					}
+				}
+            }
+        }
+    }
+    else
+    {
+        // set subscribe response callback function
+        
+    }
+    
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::unsubscribe(resultHandler resultHandler, const char* topicFilter)
+{
+	int index = 0;
+	if (this->thread)
+		index = findFreeOperation();	
+	Timer& atimer = operations[index].timer;
+
+	atimer.countdown(limits.command_timeout_ms);
+    MQTTString topic = {(char*)topicFilter, 0, 0};
+    
+    int len = MQTTSerialize_unsubscribe(buf, limits.MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic);
+    int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
+	if (rc != len) 
+		goto exit; // there was a problem
+    
+    // set unsubscribe response callback function
+        
+    
+exit:
+    return rc;
+}
+
+
+   
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::publish(resultHandler resultHandler, const char* topicName, Message* message)
+{
+	int index = 0;
+	if (this->thread)
+		index = findFreeOperation();	
+	Timer& atimer = operations[index].timer;
+
+	atimer.countdown(limits.command_timeout_ms);
+    MQTTString topic = {(char*)topicName, 0, 0};
+
+	if (message->qos == QOS1 || message->qos == QOS2)
+		message->id = packetid.getNext();
+    
+	int len = MQTTSerialize_publish(buf, limits.MAX_MQTT_PACKET_SIZE, 0, message->qos, message->retained, message->id, topic, (char*)message->payload, message->payloadlen);
+    int rc = sendPacket(len, atimer.left_ms()); // send the subscribe packet
+	if (rc != len) 
+		goto exit; // there was a problem
+    
+    /* wait for acks */
+    if (resultHandler == 0)
+    {
+ 		if (message->qos == QOS1)
+		{
+	        if (waitfor(PUBACK, atimer) == PUBACK)
+    	    {
+    	        int type, dup, mypacketid;
+    	        if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+    	            rc = 0; 
+    	    }
+		}
+		else if (message->qos == QOS2)
+		{
+	        if (waitfor(PUBCOMP, atimer) == PUBCOMP)
+	   	    {
+	   	    	int type, dup, mypacketid;
+            	if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, limits.MAX_MQTT_PACKET_SIZE) == 1)
+    	           	rc = 0; 
+			}
+
+		}
+    }
+    else
+    {
+        // set publish response callback function
+        
+    }
+    
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, class Thread, class Mutex> int MQTT::Async<Network, Timer, Thread, Mutex>::disconnect(resultHandler resultHandler)
+{  
+    Timer timer = Timer(limits.command_timeout_ms);     // we might wait for incomplete incoming publishes to complete
+    int len = MQTTSerialize_disconnect(buf, limits.MAX_MQTT_PACKET_SIZE);
+    int rc = sendPacket(len, timer.left_ms());   // send the disconnect packet
+    
+    return (rc == len) ? 0 : -1;
+}
+
+
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTClient.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,939 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 IBM Corp.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ *
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *   http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors: *
+ *    Ian Craggs - initial API and implementation and/or initial documentation
+ *    Ian Craggs - fix for bug 458512 - QoS 2 messages
+ *    Ian Craggs - fix for bug 460389 - send loop uses wrong length
+ *    Ian Craggs - fix for bug 464169 - clearing subscriptions
+ *    Ian Craggs - fix for bug 464551 - enums and ints can be different size
+ *******************************************************************************/
+
+#if !defined(MQTTCLIENT_H)
+#define MQTTCLIENT_H
+
+#include "FP.h"
+#include "MQTTPacket.h"
+#include "stdio.h"
+#include "MQTTLogging.h"
+
+#if !defined(MQTTCLIENT_QOS1)
+    #define MQTTCLIENT_QOS1 1
+#endif
+#if !defined(MQTTCLIENT_QOS2)
+    #define MQTTCLIENT_QOS2 0
+#endif
+
+namespace MQTT
+{
+
+
+enum QoS { QOS0, QOS1, QOS2 };
+
+// all failure return codes must be negative
+enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
+
+
+struct Message
+{
+    enum QoS qos;
+    bool retained;
+    bool dup;
+    unsigned short id;
+    void *payload;
+    size_t payloadlen;
+};
+
+
+struct MessageData
+{
+    MessageData(MQTTString &aTopicName, struct Message &aMessage)  : message(aMessage), topicName(aTopicName)
+    { }
+
+    struct Message &message;
+    MQTTString &topicName;
+};
+
+
+class PacketId
+{
+public:
+    PacketId()
+    {
+        next = 0;
+    }
+
+    int getNext()
+    {
+        return next = (next == MAX_PACKET_ID) ? 1 : ++next;
+    }
+
+private:
+    static const int MAX_PACKET_ID = 65535;
+    int next;
+};
+
+
+/**
+ * @class Client
+ * @brief blocking, non-threaded MQTT client API
+ *
+ * This version of the API blocks on all method calls, until they are complete.  This means that only one
+ * MQTT request can be in process at any one time.
+ * @param Network a network class which supports send, receive
+ * @param Timer a timer class with the methods:
+ */
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5>
+class Client
+{
+
+public:
+
+    typedef void (*messageHandler)(MessageData&);
+
+    /** Construct the client
+     *  @param network - pointer to an instance of the Network class - must be connected to the endpoint
+     *      before calling MQTT connect
+     *  @param limits an instance of the Limit class - to alter limits as required
+     */
+    Client(Network& network, unsigned int command_timeout_ms = 30000);
+
+    /** Set the default message handling callback - used for any message which does not match a subscription message handler
+     *  @param mh - pointer to the callback function
+     */
+    void setDefaultMessageHandler(messageHandler mh)
+    {
+        defaultMessageHandler.attach(mh);
+    }
+
+    /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+     *  The nework object must be connected to the network endpoint before calling this
+     *  Default connect options are used
+     *  @return success code -
+     */
+    int connect();
+    
+        /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
+     *  The nework object must be connected to the network endpoint before calling this
+     *  @param options - connect options
+     *  @return success code -
+     */
+    int connect(MQTTPacket_connectData& options);
+
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param message - the message to send
+     *  @return success code -
+     */
+    int publish(const char* topicName, Message& message);
+    
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param payload - the data to send
+     *  @param payloadlen - the length of the data
+     *  @param qos - the QoS to send the publish at
+     *  @param retained - whether the message should be retained
+     *  @return success code -
+     */
+    int publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos = QOS0, bool retained = false);
+    
+    /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
+     *  @param topic - the topic to publish to
+     *  @param payload - the data to send
+     *  @param payloadlen - the length of the data
+     *  @param id - the packet id used - returned 
+     *  @param qos - the QoS to send the publish at
+     *  @param retained - whether the message should be retained
+     *  @return success code -
+     */
+    int publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos = QOS1, bool retained = false);
+
+    /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @param qos - the MQTT QoS to subscribe at
+     *  @param mh - the callback function to be invoked when a message is received for this subscription
+     *  @return success code -
+     */
+    int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh);
+
+    /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback
+     *  @param topicFilter - a topic pattern which can include wildcards
+     *  @return success code -
+     */
+    int unsubscribe(const char* topicFilter);
+
+    /** MQTT Disconnect - send an MQTT disconnect packet, and clean up any state
+     *  @return success code -
+     */
+    int disconnect();
+
+    /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive
+     *  yield can be called if no other MQTT operation is needed.  This will also allow messages to be
+     *  received.
+     *  @param timeout_ms the time to wait, in milliseconds
+     *  @return success code - on failure, this means the client has disconnected
+     */
+    int yield(unsigned long timeout_ms = 1000L);
+
+    /** Is the client connected?
+     *  @return flag - is the client connected or not?
+     */
+    bool isConnected()
+    {
+        return isconnected;
+    }
+
+private:
+
+    void cleanSession();
+    int cycle(Timer& timer);
+    int waitfor(int packet_type, Timer& timer);
+    int keepalive();
+    int publish(int len, Timer& timer, enum QoS qos);
+
+    int decodePacket(int* value, int timeout);
+    int readPacket(Timer& timer);
+    int sendPacket(int length, Timer& timer);
+    int deliverMessage(MQTTString& topicName, Message& message);
+    bool isTopicMatched(char* topicFilter, MQTTString& topicName);
+
+    Network& ipstack;
+    unsigned long command_timeout_ms;
+
+    unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
+    unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
+
+    Timer last_sent, last_received;
+    unsigned int keepAliveInterval;
+    bool ping_outstanding;
+    bool cleansession;
+
+    PacketId packetid;
+
+    struct MessageHandlers
+    {
+        const char* topicFilter;
+        FP<void, MessageData&> fp;
+    } messageHandlers[MAX_MESSAGE_HANDLERS];      // Message handlers are indexed by subscription topic
+
+    FP<void, MessageData&> defaultMessageHandler;
+
+    bool isconnected;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    unsigned char pubbuf[MAX_MQTT_PACKET_SIZE];  // store the last publish for sending on reconnect
+    int inflightLen;
+    unsigned short inflightMsgid;
+    enum QoS inflightQoS;
+#endif
+
+#if MQTTCLIENT_QOS2
+    bool pubrel;
+    #if !defined(MAX_INCOMING_QOS2_MESSAGES)
+        #define MAX_INCOMING_QOS2_MESSAGES 10
+    #endif
+    unsigned short incomingQoS2messages[MAX_INCOMING_QOS2_MESSAGES];
+    bool isQoS2msgidFree(unsigned short id);
+    bool useQoS2msgid(unsigned short id);
+    void freeQoS2msgid(unsigned short id);
+#endif
+
+};
+
+}
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::cleanSession() 
+{
+    ping_outstanding = false;
+    for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+        messageHandlers[i].topicFilter = 0;
+    isconnected = false;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    inflightMsgid = 0;
+    inflightQoS = QOS0;
+#endif
+
+#if MQTTCLIENT_QOS2
+    pubrel = false;
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+        incomingQoS2messages[i] = 0;
+#endif
+}
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms)  : ipstack(network), packetid()
+{
+    last_sent = Timer();
+    last_received = Timer();
+    this->command_timeout_ms = command_timeout_ms;
+    cleanSession();
+}
+
+
+#if MQTTCLIENT_QOS2
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::isQoS2msgidFree(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == id)
+            return false;
+    }
+    return true;
+}
+
+
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::useQoS2msgid(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == 0)
+        {
+            incomingQoS2messages[i] = id;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+template<class Network, class Timer, int a, int b>
+void MQTT::Client<Network, Timer, a, b>::freeQoS2msgid(unsigned short id)
+{
+    for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
+    {
+        if (incomingQoS2messages[i] == id)
+        {
+            incomingQoS2messages[i] = 0;
+            return;
+        }
+    }
+}
+#endif
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer)
+{
+    int rc = FAILURE,
+        sent = 0;
+
+    while (sent < length && !timer.expired())
+    {
+        rc = ipstack.write(&sendbuf[sent], length - sent, timer.left_ms());
+        if (rc < 0)  // there was an error writing the data
+            break;
+        sent += rc;
+    }
+    if (sent == length)
+    {
+        if (this->keepAliveInterval > 0)
+            last_sent.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet
+        rc = SUCCESS;
+    }
+    else
+        rc = FAILURE;
+        
+#if defined(MQTT_DEBUG)
+    char printbuf[150];
+    DEBUG("Rc %d from sending packet %s\n", rc, MQTTFormat_toServerString(printbuf, sizeof(printbuf), sendbuf, length));
+#endif
+    return rc;
+}
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::decodePacket(int* value, int timeout)
+{
+    unsigned char c;
+    int multiplier = 1;
+    int len = 0;
+    const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
+
+    *value = 0;
+    do
+    {
+        int rc = MQTTPACKET_READ_ERROR;
+
+        if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
+        {
+            rc = MQTTPACKET_READ_ERROR; /* bad data */
+            goto exit;
+        }
+        rc = ipstack.read(&c, 1, timeout);
+        if (rc != 1)
+            goto exit;
+        *value += (c & 127) * multiplier;
+        multiplier *= 128;
+    } while ((c & 128) != 0);
+exit:
+    return len;
+}
+
+
+/**
+ * If any read fails in this method, then we should disconnect from the network, as on reconnect
+ * the packets can be retried.
+ * @param timeout the max time to wait for the packet read to complete, in milliseconds
+ * @return the MQTT packet type, or -1 if none
+ */
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::readPacket(Timer& timer)
+{
+    int rc = FAILURE;
+    MQTTHeader header = {0};
+    int len = 0;
+    int rem_len = 0;
+
+    /* 1. read the header byte.  This has the packet type in it */
+    if (ipstack.read(readbuf, 1, timer.left_ms()) != 1)
+        goto exit;
+
+    len = 1;
+    /* 2. read the remaining length.  This is variable in itself */
+    decodePacket(&rem_len, timer.left_ms());
+    len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
+
+    if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
+    {
+        rc = BUFFER_OVERFLOW;
+        goto exit;
+    }
+
+    /* 3. read the rest of the buffer using a callback to supply the rest of the data */
+    if (rem_len > 0 && (ipstack.read(readbuf + len, rem_len, timer.left_ms()) != rem_len))
+        goto exit;
+
+    header.byte = readbuf[0];
+    rc = header.bits.type;
+    if (this->keepAliveInterval > 0)
+        last_received.countdown(this->keepAliveInterval); // record the fact that we have successfully received a packet
+exit:
+        
+#if defined(MQTT_DEBUG)
+    if (rc >= 0)
+    {
+        char printbuf[50];
+        DEBUG("Rc %d from receiving packet %s\n", rc, MQTTFormat_toClientString(printbuf, sizeof(printbuf), readbuf, len));
+    }
+#endif
+    return rc;
+}
+
+
+// assume topic filter and name is in correct format
+// # can only be at end
+// + and # can only be next to separator
+template<class Network, class Timer, int a, int b>
+bool MQTT::Client<Network, Timer, a, b>::isTopicMatched(char* topicFilter, MQTTString& topicName)
+{
+    char* curf = topicFilter;
+    char* curn = topicName.lenstring.data;
+    char* curn_end = curn + topicName.lenstring.len;
+
+    while (*curf && curn < curn_end)
+    {
+        if (*curn == '/' && *curf != '/')
+            break;
+        if (*curf != '+' && *curf != '#' && *curf != *curn)
+            break;
+        if (*curf == '+')
+        {   // skip until we meet the next separator, or end of string
+            char* nextpos = curn + 1;
+            while (nextpos < curn_end && *nextpos != '/')
+                nextpos = ++curn + 1;
+        }
+        else if (*curf == '#')
+            curn = curn_end - 1;    // skip until end of string
+        curf++;
+        curn++;
+    };
+
+    return (curn == curn_end) && (*curf == '\0');
+}
+
+
+
+template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTString& topicName, Message& message)
+{
+    int rc = FAILURE;
+
+    // we have to find the right message handler - indexed by topic
+    for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+    {
+        if (messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(&topicName, (char*)messageHandlers[i].topicFilter) ||
+                isTopicMatched((char*)messageHandlers[i].topicFilter, topicName)))
+        {
+            if (messageHandlers[i].fp.attached())
+            {
+                MessageData md(topicName, message);
+                messageHandlers[i].fp(md);
+                rc = SUCCESS;
+            }
+        }
+    }
+
+    if (rc == FAILURE && defaultMessageHandler.attached())
+    {
+        MessageData md(topicName, message);
+        defaultMessageHandler(md);
+        rc = SUCCESS;
+    }
+
+    return rc;
+}
+
+
+
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::yield(unsigned long timeout_ms)
+{
+    int rc = SUCCESS;
+    Timer timer = Timer();
+
+    timer.countdown_ms(timeout_ms);
+    while (!timer.expired())
+    {
+        if (cycle(timer) < 0)
+        {
+            rc = FAILURE;
+            break;
+        }
+    }
+
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle(Timer& timer)
+{
+    /* get one piece of work off the wire and one pass through */
+
+    // read the socket, see what work is due
+    int packet_type = readPacket(timer);
+
+    int len = 0,
+        rc = SUCCESS;
+
+    switch (packet_type)
+    {
+        case FAILURE:
+        case BUFFER_OVERFLOW:
+            rc = packet_type;
+            break;
+        case CONNACK:
+        case PUBACK:
+        case SUBACK:
+            break;
+        case PUBLISH:
+        {
+            MQTTString topicName = MQTTString_initializer;
+            Message msg;
+            int intQoS;
+            if (MQTTDeserialize_publish((unsigned char*)&msg.dup, &intQoS, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
+                                 (unsigned char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                goto exit;
+            msg.qos = (enum QoS)intQoS;
+#if MQTTCLIENT_QOS2
+            if (msg.qos != QOS2)
+#endif
+                deliverMessage(topicName, msg);
+#if MQTTCLIENT_QOS2
+            else if (isQoS2msgidFree(msg.id))
+            {
+                if (useQoS2msgid(msg.id))
+                    deliverMessage(topicName, msg);
+                else
+                    WARN("Maximum number of incoming QoS2 messages exceeded");
+            }
+#endif
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+            if (msg.qos != QOS0)
+            {
+                if (msg.qos == QOS1)
+                    len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBACK, 0, msg.id);
+                else if (msg.qos == QOS2)
+                    len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREC, 0, msg.id);
+                if (len <= 0)
+                    rc = FAILURE;
+                else
+                    rc = sendPacket(len, timer);
+                if (rc == FAILURE)
+                    goto exit; // there was a problem
+            }
+            break;
+#endif
+        }
+#if MQTTCLIENT_QOS2
+        case PUBREC:
+        case PUBREL:
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, 
+                        (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
+                rc = FAILURE;
+            else if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet
+                rc = FAILURE; // there was a problem
+            if (rc == FAILURE)
+                goto exit; // there was a problem
+            if (packet_type == PUBREL)
+                freeQoS2msgid(mypacketid);
+            break;
+            
+        case PUBCOMP:
+            break;
+#endif
+        case PINGRESP:
+            ping_outstanding = false;
+            break;
+    }
+    keepalive();
+exit:
+    if (rc == SUCCESS)
+        rc = packet_type;
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::keepalive()
+{
+    int rc = FAILURE;
+
+    if (keepAliveInterval == 0)
+    {
+        rc = SUCCESS;
+        goto exit;
+    }
+
+    if (last_sent.expired() || last_received.expired())
+    {
+        if (!ping_outstanding)
+        {
+            Timer timer(1000);
+            int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
+            if (len > 0 && (rc = sendPacket(len, timer)) == SUCCESS) // send the ping packet
+                ping_outstanding = true;
+        }
+    }
+
+exit:
+    return rc;
+}
+
+
+// only used in single-threaded mode where one command at a time is in process
+template<class Network, class Timer, int a, int b>
+int MQTT::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer)
+{
+    int rc = FAILURE;
+
+    do
+    {
+        if (timer.expired())
+            break; // we timed out
+    }
+    while ((rc = cycle(timer)) != packet_type);
+
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options)
+{
+    Timer connect_timer(command_timeout_ms);
+    int rc = FAILURE;
+    int len = 0;
+
+    if (isconnected) // don't send connect packet again if we are already connected
+        goto exit;
+
+    this->keepAliveInterval = options.keepAliveInterval;
+    this->cleansession = options.cleansession;
+    if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &options)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, connect_timer)) != SUCCESS)  // send the connect packet
+        goto exit; // there was a problem
+
+    if (this->keepAliveInterval > 0)
+        last_received.countdown(this->keepAliveInterval);
+    // this will be a blocking call, wait for the connack
+    if (waitfor(CONNACK, connect_timer) == CONNACK)
+    {
+        unsigned char connack_rc = 255;
+        bool sessionPresent = false;
+        if (MQTTDeserialize_connack((unsigned char*)&sessionPresent, &connack_rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+            rc = connack_rc;
+        else
+            rc = FAILURE;
+    }
+    else
+        rc = FAILURE;
+
+#if MQTTCLIENT_QOS2
+    // resend any inflight publish
+    if (inflightMsgid > 0 && inflightQoS == QOS2 && pubrel)
+    {
+        if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREL, 0, inflightMsgid)) <= 0)
+            rc = FAILURE;
+        else
+            rc = publish(len, connect_timer, inflightQoS);
+    }
+    else
+#endif
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (inflightMsgid > 0)
+    {
+        memcpy(sendbuf, pubbuf, MAX_MQTT_PACKET_SIZE);
+        rc = publish(inflightLen, connect_timer, inflightQoS);
+    }
+#endif
+
+exit:
+    if (rc == SUCCESS)
+        isconnected = true;
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect()
+{
+    MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
+    return connect(default_options);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter, enum QoS qos, messageHandler messageHandler)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    int len = 0;
+    MQTTString topic = {(char*)topicFilter, {0, 0}};
+
+    if (!isconnected)
+        goto exit;
+
+    len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
+    if (len <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet
+        goto exit;             // there was a problem
+
+    if (waitfor(SUBACK, timer) == SUBACK)      // wait for suback
+    {
+        int count = 0, grantedQoS = -1;
+        unsigned short mypacketid;
+        if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+            rc = grantedQoS; // 0, 1, 2 or 0x80
+        if (rc != 0x80)
+        {
+            for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (messageHandlers[i].topicFilter == 0)
+                {
+                    messageHandlers[i].topicFilter = topicFilter;
+                    messageHandlers[i].fp.attach(messageHandler);
+                    rc = 0;
+                    break;
+                }
+            }
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc != SUCCESS)
+        cleanSession();
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(const char* topicFilter)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    MQTTString topic = {(char*)topicFilter, {0, 0}};
+    int len = 0;
+
+    if (!isconnected)
+        goto exit;
+
+    if ((len = MQTTSerialize_unsubscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic)) <= 0)
+        goto exit;
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the unsubscribe packet
+        goto exit; // there was a problem
+
+    if (waitfor(UNSUBACK, timer) == UNSUBACK)
+    {
+        unsigned short mypacketid;  // should be the same as the packetid above
+        if (MQTTDeserialize_unsuback(&mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
+        {
+            rc = 0;
+
+            // remove the subscription message handler associated with this topic, if there is one
+            for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
+            {
+                if (messageHandlers[i].topicFilter && strcmp(messageHandlers[i].topicFilter, topicFilter) == 0)
+                {
+                    messageHandlers[i].topicFilter = 0;
+                    break;
+                }
+            }
+        }
+    }
+    else
+        rc = FAILURE;
+
+exit:
+    if (rc != SUCCESS)
+        cleanSession();
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(int len, Timer& timer, enum QoS qos)
+{
+    int rc;
+
+    if ((rc = sendPacket(len, timer)) != SUCCESS) // send the publish packet
+        goto exit; // there was a problem
+
+#if MQTTCLIENT_QOS1
+    if (qos == QOS1)
+    {
+        if (waitfor(PUBACK, timer) == PUBACK)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if (inflightMsgid == mypacketid)
+                inflightMsgid = 0;
+        }
+        else
+            rc = FAILURE;
+    }
+#elif MQTTCLIENT_QOS2
+    else if (qos == QOS2)
+    {
+        if (waitfor(PUBCOMP, timer) == PUBCOMP)
+        {
+            unsigned short mypacketid;
+            unsigned char dup, type;
+            if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
+                rc = FAILURE;
+            else if (inflightMsgid == mypacketid)
+                inflightMsgid = 0;
+        }
+        else
+            rc = FAILURE;
+    }
+#endif
+
+exit:
+    if (rc != SUCCESS)
+        cleanSession();
+    return rc;
+}
+
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos, bool retained)
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);
+    MQTTString topicString = MQTTString_initializer;
+    int len = 0;
+
+    if (!isconnected)
+        goto exit;
+
+    topicString.cstring = (char*)topicName;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (qos == QOS1 || qos == QOS2)
+        id = packetid.getNext();
+#endif
+
+    len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, qos, retained, id,
+              topicString, (unsigned char*)payload, payloadlen);
+    if (len <= 0)
+        goto exit;
+
+#if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
+    if (!cleansession)
+    {
+        memcpy(pubbuf, sendbuf, len);
+        inflightMsgid = id;
+        inflightLen = len;
+        inflightQoS = qos;
+#if MQTTCLIENT_QOS2
+        pubrel = false;
+#endif
+    }
+#endif
+
+    rc = publish(len, timer, qos);
+exit:
+    return rc;
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos, bool retained)
+{
+    unsigned short id = 0;  // dummy - not used for anything
+    return publish(topicName, payload, payloadlen, id, qos, retained);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, Message& message)
+{
+    return publish(topicName, message.payload, message.payloadlen, message.qos, message.retained);
+}
+
+
+template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
+int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::disconnect()
+{
+    int rc = FAILURE;
+    Timer timer(command_timeout_ms);            // we might wait for incomplete incoming publishes to complete
+    int len = MQTTSerialize_disconnect(sendbuf, MAX_MQTT_PACKET_SIZE);
+    if (len > 0)
+        rc = sendPacket(len, timer);            // send the disconnect packet
+
+    if (cleansession)
+        cleanSession();
+    else
+        isconnected = false;
+    return rc;
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTEthernet.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,35 @@
+
+#if !defined(MQTTETHERNET_H)
+#define MQTTETHERNET_H
+
+#include "MQTTmbed.h"
+#include "EthernetInterface.h"
+#include "MQTTSocket.h"
+
+class MQTTEthernet : public MQTTSocket
+{
+public:    
+    MQTTEthernet()
+    {
+        eth.init();                          // Use DHCP
+        eth.connect();
+    }
+    
+    EthernetInterface& getEth()
+    {
+        return eth;
+    }
+    
+    void reconnect()
+    {
+        eth.connect();  // nothing I've tried actually works to reconnect 
+    }
+    
+private:
+
+    EthernetInterface eth;
+    
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTLogging.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,39 @@
+#if !defined(MQTT_LOGGING_H)
+#define MQTT_LOGGING_H
+
+#define STREAM      stdout
+#if !defined(DEBUG)
+#define DEBUG(...)    \
+    {\
+    fprintf(STREAM, "DEBUG:   %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif
+#if !defined(LOG)
+#define LOG(...)    \
+    {\
+    fprintf(STREAM, "LOG:   %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif
+#if !defined(WARN)
+#define WARN(...)   \
+    { \
+    fprintf(STREAM, "WARN:  %s L#%d ", __PRETTY_FUNCTION__, __LINE__);  \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    }
+#endif 
+#if !defined(ERROR)
+#define ERROR(...)  \
+    { \
+    fprintf(STREAM, "ERROR: %s L#%d ", __PRETTY_FUNCTION__, __LINE__); \
+    fprintf(STREAM, ##__VA_ARGS__); \
+    fflush(STREAM); \
+    exit(1); \
+    }
+#endif
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTPacket.lib	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+http://mbed.org/teams/mqtt/code/MQTTPacket/#62396c1620b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTSocket.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,118 @@
+#if !defined(MQTTSOCKET_H)
+#define MQTTSOCKET_H
+
+#include "MQTTmbed.h"
+#include "TCPSocket.h"
+
+class MQTTSocket
+{
+public:
+
+	MQTTSocket(): mysock(true)
+	{
+
+	}
+
+    int open(NetworkStack *ipstack)
+    {
+    	_time_last_ticks = 0;
+    	timesock.open(ipstack);
+    	return mysock.open(ipstack);
+    }
+
+    int getNTPtime(int timeout=1000)
+    {
+    	int err;
+
+    	uint8_t timedata[4];
+
+		timesock.set_timeout(timeout*3);
+		do
+		{
+			err= timesock.connect("time-d.nist.gov", 37);
+
+			if (err != 0)
+			{
+				LOG("ERROR resolving ntp server IP and connecting to it! \r\n");
+			}
+		} while (err != 0);
+
+		while (err != 4)
+		{
+			err = timesock.recv((char*)timedata, 4);
+
+			if (err != 4)
+			{
+				LOG("ERROR receiving time from ntp server! \r\n");
+				//return -1;
+			}
+			else
+			{
+				///
+				/// Time Protocol provides the time as a binary number of seconds since 1900,
+				///
+				/// 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT from 12:00:01 am on 1 January 1900 GMT
+				///
+				_time_last_ticks = ((timedata[0]<<24 )|(timedata[1]<<16)|(timedata[2]<<8)| timedata[3]) - 2208988800ul;
+
+				LOG("Success receiving time from ntp server. Tick from 1 Jan 1970 is equal to %d. \r\n", _time_last_ticks);
+
+			}
+		}
+
+		err = timesock.close();
+
+		return err;
+    }
+
+    int connect(char* hostname, int port, int timeout=1000)
+    {
+        int err;
+
+        mysock.set_timeout(timeout);
+        err = mysock.connect(hostname, port);  
+//    t.start();             
+        return err; 
+    }
+
+    int read(unsigned char* buffer, int len, int timeout)
+    {
+        mysock.set_timeout(timeout);        
+//t.reset();
+// int start = t.read_ms();
+        int rc = mysock.recv((char*)buffer, len);
+// int stop = t.read_ms();       
+//        if (rc>0) printf ("recv File: %s, Line: %d Read nB: %d rc: %d timeout: %d elaps: %d\n\r",__FILE__,__LINE__, len, rc, timeout, stop-start);        
+        return rc;
+    }
+    
+    int write(unsigned char* buffer, int len, int timeout)
+    {
+        mysock.set_timeout(timeout);                
+//        mysock.set_blocking(false, timeout);  
+//        mysock.set_blocking(false);  
+        int rc = mysock.send((char*)buffer, len);
+//         printf ("send File: %s, Line: %d Write nB: %d rc: %d\n\r",__FILE__,__LINE__, len, rc);
+        return rc;
+    }
+    
+    int disconnect()
+    {
+//        t.stop();
+        return mysock.close();
+    }
+
+    inline int getTime()
+    {
+    	return _time_last_ticks;
+    }
+     
+private:
+    TCPSocket mysock; 
+    TCPSocket timesock;
+
+    uint32_t _time_last_ticks;
+ //   Timer t;
+    
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTWiFi.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,30 @@
+
+#if !defined(MQTTWIFI_H)
+#define MQTTWIFI_H
+
+#include "MQTTmbed.h"
+#include "WiFiInterface.h"
+#include "MQTTSocket.h"
+
+class MQTTWiFi : public MQTTSocket
+{
+public:    
+    MQTTWiFi(SpwfSAInterface &WiFiIntf, const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) : WiFi(WiFiIntf)
+    {
+    	WiFi.reset_chip();
+        WiFi.connect(ssid, pass,  security);
+    }
+    
+    SpwfSAInterface& getWiFi()
+    {
+        return WiFi;
+    }
+
+private:
+
+    SpwfSAInterface& WiFi;
+    
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/MQTTmbed.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,49 @@
+#if !defined(MQTT_MBED_H)
+#define MQTT_MBED_H
+
+#include "mbed.h"
+
+class Countdown
+{
+public:
+    Countdown()
+    {
+        t = Timer();   
+    }
+    
+    Countdown(int ms)
+    {
+        t = Timer();
+        countdown_ms(ms);   
+    }
+    
+    
+    bool expired()
+    {
+        return t.read_ms() >= interval_end_ms;
+    }
+    
+    void countdown_ms(unsigned long ms)  
+    {
+        t.stop();
+        interval_end_ms = ms;
+        t.reset();
+        t.start();
+    }
+    
+    void countdown(int seconds)
+    {
+        countdown_ms((unsigned long)seconds * 1000L);
+    }
+    
+    int left_ms()
+    {
+        return interval_end_ms - t.read_ms();
+    }
+    
+private:
+    Timer t;
+    unsigned long interval_end_ms; 
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MQTT/NOTICE.TXT	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,4 @@
+
+This library is originated from https://developer.mbed.org/teams/ST/code/MQTT/#66826ea709ea
+MQTTWiFi class was modified to support hardware wifi reset.
+MQTTSocket class was modified to support NTP server time request.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NOTICE.txt	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,2 @@
+This project is originally got from https://developer.mbed.org/teams/ST/code/IDW01M1_Cloud_IBM/
+It was completely adopted to Amazon AWS services. IBM IoT service connection is not supported.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/CellularInterface.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,51 @@
+/* CellularInterface
+ * 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 CELLULAR_INTERFACE_H
+#define CELLULAR_INTERFACE_H
+ 
+#include "NetworkStack.h"
+ 
+/** CellularInterface class
+ *
+ *  Common interface that is shared between ethernet hardware
+ */
+class CellularInterface
+{
+public:
+    /** Start the interface
+     *
+     *  @param apn      Optional name of the network to connect to
+     *  @param username Optional username for your APN
+     *  @param password Optional password for your APN 
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect(const char *apn = 0, const char *username = 0, const char *password = 0) = 0;
+ 
+    /** Stop the interface
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int disconnect() = 0;
+
+    /** Get the local MAC address
+     *
+     *  @return         Null-terminated representation of the local MAC address
+     */
+    virtual const char *get_mac_address() = 0;
+};
+ 
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/DnsQuery.lib	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/NetworkSocketAPI/code/DnsQuery/#2cb1fffed50c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/EthernetInterface.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,48 @@
+/* EthernetInterface
+ * 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 ETHERNET_INTERFACE_H
+#define ETHERNET_INTERFACE_H
+
+#include "NetworkStack.h"
+
+/** EthernetInterface class
+ *
+ *  Common interface that is shared between ethernet hardware.
+ */
+class EthernetInterface
+{
+public:
+    /** Start the interface
+     *
+     *  @return     0 on success, negative error code on failure
+     */
+    virtual int connect() = 0;
+
+    /** Stop the interface
+     *
+     *  @return     0 on success, negative error code on failure
+     */
+    virtual int disconnect() = 0;
+
+    /** Get the local MAC address
+     *
+     *  @return         Null-terminated representation of the local MAC address
+     */
+    virtual const char *get_mac_address() = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/MeshInterface.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,48 @@
+/* MeshInterface
+ * 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 MESH_INTERFACE_H
+#define MESH_INTERFACE_H
+
+#include "NetworkStack.h"
+
+/** MeshInterface class
+ *
+ *  Common interface that is shared between mesh hardware
+ */
+class MeshInterface
+{
+public:
+    /** Start the interface
+     *
+     *  @return     0 on success, negative on failure
+     */
+    virtual int connect() = 0;
+
+    /** Stop the interface
+     *
+     *  @return     0 on success, negative on failure
+     */
+    virtual int disconnect() = 0;
+
+    /** Get the local MAC address
+     *
+     *  @return         Null-terminated representation of the local MAC address
+     */
+    virtual const char *get_mac_address() = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/NOTICE.txt	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,3 @@
+This library is origionated from http://mbed.org/teams/NetworkSocketAPI/code/NetworkSocketAPI/#ea3a618e0818
+"enum nsapi_protocol_t" is extended with security socket
+"class TCPSocket" is extended with security socket support
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/NetworkStack.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,50 @@
+/* Socket
+ * 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 "DnsQuery.h"
+#include "mbed.h"
+
+int NetworkStack::gethostbyname(SocketAddress *address, const char *name)
+{
+    char buffer[NSAPI_IP_SIZE];
+    int err = dnsQuery(this, name, buffer);
+    if (err) {
+        return err;
+    }
+
+    address->set_ip_address(buffer);
+    return 0;
+}
+
+int NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int NetworkStack::getstackopt(int level, int optname, void *optval, unsigned *optlen)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int NetworkStack::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int NetworkStack::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/NetworkStack.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,339 @@
+/* NetworkStack
+ * 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 NETWORK_INTERFACE_H
+#define NETWORK_INTERFACE_H
+
+#include "mbed.h"
+#include "SocketAddress.h"
+
+
+/** Enum of standardized error codes 
+ *
+ *  Valid error codes have negative values and may
+ *  be returned by any network operation.
+ *
+ *  @enum nsapi_error_t
+ */
+enum nsapi_error_t {
+    NSAPI_ERROR_WOULD_BLOCK   = -3001,     /*!< no data is not available but call is non-blocking */
+    NSAPI_ERROR_UNSUPPORTED   = -3002,     /*!< unsupported functionality */
+    NSAPI_ERROR_PARAMETER     = -3003,     /*!< invalid configuration */
+    NSAPI_ERROR_NO_CONNECTION = -3004,     /*!< not connected to a network */
+    NSAPI_ERROR_NO_SOCKET     = -3005,     /*!< socket not available for use */
+    NSAPI_ERROR_NO_ADDRESS    = -3006,     /*!< IP address is not known */
+    NSAPI_ERROR_NO_MEMORY     = -3007,     /*!< memory resource not available */
+    NSAPI_ERROR_DNS_FAILURE   = -3008,     /*!< DNS failed to complete successfully */
+    NSAPI_ERROR_DHCP_FAILURE  = -3009,     /*!< DHCP failed to complete successfully */
+    NSAPI_ERROR_AUTH_FAILURE  = -3010,     /*!< connection to access point faield */
+    NSAPI_ERROR_DEVICE_ERROR  = -3011,     /*!< failure interfacing with the network procesor */
+};
+
+/** Enum of socket protocols
+ *
+ *  The socket protocol specifies a particular protocol to
+ *  be used with a newly created socket. 
+ *
+ *  @enum nsapi_protocol_t
+ */
+enum nsapi_protocol_t {
+   NSAPI_TCP, /*!< Socket is of TCP type */
+   NSAPI_UDP, /*!< Socket is of UDP type */
+   NSAPI_TLS  /*!< Socket is of TCP Secure type */
+};
+
+/*  Enum of standardized stack option levels
+ *
+ *  @enum nsapi_level_t
+ */
+enum nsapi_level_t {
+    NSAPI_STACK,  /*!< Stack option level */
+    NSAPI_SOCKET, /*!< Socket option level */
+};
+
+/*  Enum of standardized stack options
+ *
+ *  These options may not be supported on all stacks, in which
+ *  case NSAPI_ERROR_UNSUPPORTED may be returned from setsockopt.
+ *
+ *  @enum nsapi_option_t
+ */
+enum nsapi_option_t {
+    NSAPI_REUSEADDR, /*!< Allow bind to reuse local addresses */
+    NSAPI_KEEPALIVE, /*!< Enables sending of keepalive messages */
+    NSAPI_LINGER,    /*!< Keeps close from returning until queues empty */
+    NSAPI_SNDBUF,    /*!< Sets send buffer size */
+    NSAPI_RCVBUF,    /*!< Sets recv buffer size */
+};
+
+
+/** NetworkStack class
+ *
+ *  Common interface that is shared between hardware that
+ *  can connect to a network over IP. By implementing the
+ *  NetworkStack, a network stack can be used as a target
+ *  for instantiating network sockets.
+ */
+class NetworkStack
+{
+public:
+    virtual ~NetworkStack() {};
+
+    /** Get the local IP address
+     *
+     *  @return         Null-terminated representation of the local IP address
+     *                  or null if not yet connected
+     */
+    virtual const char *get_ip_address() = 0;
+
+    /** Translates a hostname to an IP address
+     *
+     *  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
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int gethostbyname(SocketAddress *address, const char *host);
+
+    /*  Set stack-specific stack options
+     *
+     *  The setstackopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the stack is unmodified.
+     *
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    virtual int setstackopt(int level, int optname, const void *optval, unsigned optlen);
+
+    /*  Get stack-specific stack options
+     *
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    virtual int getstackopt(int level, int optname, void *optval, unsigned *optlen);
+
+protected:
+    friend class Socket;
+    friend class UDPSocket;
+    friend class TCPSocket;
+    friend class TCPServer;
+
+    /** Opens a socket
+     *
+     *  Creates a network socket and stores it in the specified handle.
+     *  The handle must be passed to following calls on the socket.
+     *
+     *  A stack may have a finite number of sockets, in this case
+     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
+     *
+     *  @param handle   Destination for the handle to a newly created socket
+     *  @param proto    Protocol of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto) = 0;
+
+    /** Close the socket
+     *
+     *  Closes any open connection and deallocates any memory associated
+     *  with the socket.
+     *
+     *  @param handle   Socket handle
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int socket_close(void *handle) = 0;
+
+    /** Bind a specific address to a socket
+     *
+     *  Binding a socket specifies the address and port on which to recieve
+     *  data. If the IP address is zeroed, only the port is bound.
+     *
+     *  @param handle   Socket handle
+     *  @param address  Local address to bind
+     *  @return         0 on success, negative error code on failure.
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address) = 0;
+
+    /** Listen for connections on a TCP socket
+     *
+     *  Marks the socket as a passive socket that can be used to accept
+     *  incoming connections.
+     *
+     *  @param handle   Socket handle
+     *  @param backlog  Number of pending connections that can be queued
+     *                  simultaneously
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int socket_listen(void *handle, int backlog) = 0;
+
+    /** Connects TCP socket to a remote host
+     *
+     *  Initiates a connection to a remote server specified by the
+     *  indicated address.
+     *
+     *  @param handle   Socket handle
+     *  @param address  The SocketAddress of the remote host
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address) = 0;
+
+    /** Accepts a connection on a TCP socket
+     *
+     *  The server socket must be bound and set to listen for connections.
+     *  On a new connection, creates a network socket and stores it in the
+     *  specified handle. The handle must be passed to following calls on
+     *  the socket.
+     *
+     *  A stack may have a finite number of sockets, in this case
+     *  NSAPI_ERROR_NO_SOCKET is returned if no socket is available.
+     *
+     *  This call is non-blocking. If accept would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param handle   Destination for a handle to the newly created sockey
+     *  @param server   Socket handle to server to accept from
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int socket_accept(void **handle, void *server) = 0;
+
+    /** Send data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes sent from the buffer.
+     *
+     *  This call is non-blocking. If send would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param handle   Socket handle
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size) = 0;
+
+    /** Receive data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes received into the buffer.
+     *
+     *  This call is non-blocking. If recv would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param handle   Socket handle
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size) = 0;
+
+    /** Send a packet over a UDP socket
+     *
+     *  Sends data to the specified address. Returns the number of bytes
+     *  sent from the buffer.
+     *
+     *  This call is non-blocking. If sendto would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param handle   Socket handle
+     *  @param address  The SocketAddress of the remote host
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size) = 0;
+
+    /** Receive a packet over a UDP socket
+     *
+     *  Receives data and stores the source address in address if address
+     *  is not NULL. Returns the number of bytes received into the buffer.
+     *
+     *  This call is non-blocking. If recvfrom would block,
+     *  NSAPI_ERROR_WOULD_BLOCK is returned immediately.
+     *
+     *  @param handle   Socket handle
+     *  @param address  Destination for the source address or NULL
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) = 0;
+
+    /** Register a callback on state change of the socket
+     *
+     *  The specified callback will be called on state changes such as when
+     *  the socket can recv/send/accept successfully and on when an error
+     *  occurs. The callback may also be called spuriously without reason.
+     *
+     *  The callback may be called in an interrupt context and should not
+     *  perform expensive operations such as recv/send calls.
+     *
+     *  @param handle   Socket handle
+     *  @param callback Function to call on state change
+     *  @param data     Argument to pass to callback
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data) = 0;
+
+    /*  Set stack-specific socket options
+     *
+     *  The setsockopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
+     *
+     *  @param handle   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    virtual int setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen);
+
+    /*  Get stack-specific socket options
+     *
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param handle   Socket handle
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    virtual int getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/Socket.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,127 @@
+/* Socket
+ * 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 "Socket.h"
+
+Socket::Socket()
+    : _iface(0)
+    , _socket(0)
+    , _timeout(-1)
+{
+}
+
+Socket::~Socket()
+{
+    if (_socket) {
+        close();
+    }
+}
+
+int Socket::open(NetworkStack *iface, nsapi_protocol_t proto)
+{
+    _iface = iface;
+
+    void *socket;
+    int err = _iface->socket_open(&socket, proto);
+    if (err) {
+        return err;
+    }
+
+    _socket = socket;
+    _iface->socket_attach(_socket, &Socket::thunk, this);
+
+    return 0;
+}
+
+int Socket::close()
+{
+    if (!_socket) {
+        return 0;
+    }
+    
+    _iface->socket_attach(_socket, 0, 0);
+    
+    void *volatile socket = _socket;
+    _socket = 0;
+    return _iface->socket_close(socket);
+}
+
+int Socket::bind(uint16_t port)
+{
+    SocketAddress addr(0, port);
+    return bind(addr);
+}
+
+int Socket::bind(const char *address, uint16_t port)
+{
+    SocketAddress addr(address, port);
+    return bind(addr);
+}
+
+int Socket::bind(const SocketAddress &address)
+{
+    if (!_socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    return _iface->socket_bind(_socket, address);
+}
+
+void Socket::set_blocking(bool blocking)
+{
+    set_timeout(blocking ? -1 : 0);
+}
+
+void Socket::set_timeout(int timeout)
+{
+    _timeout = timeout;
+}
+
+int Socket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
+{
+    if (!_socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    return _iface->setsockopt(_socket, level, optname, optval, optlen);
+}
+
+int Socket::getsockopt(int level, int optname, void *optval, unsigned *optlen)
+{
+    if (!_socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    return _iface->getsockopt(_socket, level, optname, optval, optlen);
+
+}
+
+void Socket::wakeup()
+{
+}
+
+void Socket::thunk(void *data)
+{
+    Socket *self = (Socket *)data;
+    if (self->_callback) {
+        self->_callback();
+    }
+}
+
+void Socket::attach(FunctionPointer callback)
+{
+    _callback = callback;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/Socket.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,180 @@
+/* Socket
+ * 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 SOCKET_H
+#define SOCKET_H
+
+#include "SocketAddress.h"
+#include "NetworkStack.h"
+
+/** Abstract socket class
+ */
+class Socket {
+public:
+    /** Destroy a socket
+     *
+     *  Closes socket if the socket is still open
+     */
+    virtual ~Socket();
+
+    /** Opens a socket
+     *
+     *  Creates a network socket on the specified network stack.
+     *  Not needed if stack is passed to the socket's constructor.
+     *
+     *  @param iface    Network stack as target for socket
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(NetworkStack *iface) = 0;
+    
+    /** Close the socket
+     *
+     *  Closes any open connection and deallocates any memory associated
+     *  with the socket. Called from destructor if socket is not closed.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    int close();
+    
+    /** Bind a specific address to a socket
+     *
+     *  Binding a socket specifies the address and port on which to recieve
+     *  data.
+     *
+     *  @param port     Local port to bind
+     *  @return         0 on success, negative error code on failure.
+     */
+    int bind(uint16_t port);
+
+    /** Bind a specific address to a socket
+     *
+     *  Binding a socket specifies the address and port on which to recieve
+     *  data. If the IP address is zeroed, only the port is bound.
+     *
+     *  @param address  Null-terminated local address to bind
+     *  @param port     Local port to bind
+     *  @return         0 on success, negative error code on failure.
+     */
+    int bind(const char *address, uint16_t port);
+
+    /** Bind a specific address to a socket
+     *
+     *  Binding a socket specifies the address and port on which to recieve
+     *  data. If the IP address is zeroed, only the port is bound.
+     *
+     *  @param address  Local address to bind
+     *  @return         0 on success, negative error code on failure.
+     */
+    int bind(const SocketAddress &address);
+    
+    /** Set blocking or non-blocking mode of the socket
+     *
+     *  Initially all sockets are in blocking mode. In non-blocking mode
+     *  blocking operations such as send/recv/accept return
+     *  NSAPI_ERROR_WOULD_BLOCK if they can not continue.
+     *
+     *  set_blocking(false) is equivalent to set_timeout(-1)
+     *  set_blocking(true) is equivalent to set_timeout(0)
+     *
+     *  @param blocking true for blocking mode, false for non-blocking mode.
+     */
+    void set_blocking(bool blocking);
+    
+    /** Set timeout on blocking socket operations
+     *
+     *  Initially all sockets have unbounded timeouts. NSAPI_ERROR_WOULD_BLOCK
+     *  is returned if a blocking operation takes longer than the specified
+     *  timeout. A timeout of -1 removes the timeout from the socket.
+     *
+     *  set_timeout(-1) is equivalent to set_blocking(false)
+     *  set_timeout(0) is equivalent to set_blocking(true)
+     *
+     *  @param timeout  Timeout in milliseconds
+     */
+    void set_timeout(int timeout);
+
+    /*  Set stack-specific socket options
+     *
+     *  The setsockopt allow an application to pass stack-specific hints
+     *  to the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
+     *
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    int setsockopt(int level, int optname, const void *optval, unsigned optlen);
+
+    /*  Get stack-specific socket options
+     *
+     *  The getstackopt allow an application to retrieve stack-specific hints
+     *  from the underlying stack. For unsupported options,
+     *  NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
+     *
+     *  @param level    Stack-specific protocol level
+     *  @param optname  Stack-specific option identifier
+     *  @param optval   Destination for option value
+     *  @param optlen   Length of the option value
+     *  @return         0 on success, negative error code on failure
+     */    
+    int getsockopt(int level, int optname, void *optval, unsigned *optlen);
+
+    /** Register a callback on state change of the socket
+     *
+     *  The specified callback will be called on state changes such as when
+     *  the socket can recv/send/accept successfully and on when an error
+     *  occurs. The callback may also be called spuriously without reason.
+     *
+     *  The callback may be called in an interrupt context and should not
+     *  perform expensive operations such as recv/send calls.
+     *
+     *  @param callback Function to call on state change
+     */
+    void attach(FunctionPointer callback);
+
+    /** Register a callback on state change of the socket
+     *
+     *  The specified callback will be called on state changes such as when
+     *  the socket can recv/send/accept successfully and on when an error
+     *  occurs. The callback may also be called spuriously without reason.
+     *
+     *  The callback may be called in an interrupt context and should not
+     *  perform expensive operations such as recv/send calls.
+     *
+     *  @param tptr     Pointer to object to call method on
+     *  @param mptr     Method to call on state change
+     */
+    template <typename T, typename M>
+    void attach(T *tptr, M mptr) {
+        attach(FunctionPointer(tptr, mptr));
+    }
+
+protected:
+    Socket();
+    int open(NetworkStack *iface, nsapi_protocol_t proto);
+
+    static void thunk(void *);
+    static void wakeup();
+
+    NetworkStack *_iface;
+    void *_socket;
+    int _timeout;
+    FunctionPointer _callback;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/SocketAddress.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,275 @@
+/* Socket
+ * 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 "SocketAddress.h"
+#include "NetworkStack.h"
+#include <string.h>
+#include "mbed.h"
+
+
+static bool ipv4_is_valid(const char *addr)
+{
+    int i = 0;
+
+    // Check each digit for [0-9.]
+    for (; addr[i]; i++) {
+        if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') {
+            return false;
+        }
+    }
+
+    // Ending with '.' garuntees host
+    if (i > 0 && addr[i-1] == '.') {
+        return false;
+    }
+
+    return true;
+}
+
+static bool ipv6_is_valid(const char *addr)
+{
+    // Check each digit for [0-9a-fA-F:]
+    for (int i = 0; addr[i]; i++) {
+        if (!(addr[i] >= '0' && addr[i] <= '9') &&
+            !(addr[i] >= 'a' && addr[i] <= 'f') &&
+            !(addr[i] >= 'A' && addr[i] <= 'F') &&
+            addr[i] != ':') {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static void ipv4_from_address(uint8_t *bytes, const char *addr)
+{
+    int count = 0;
+    int i = 0;
+
+    for (; count < NSAPI_IPv4_BYTES; count++) {
+        int scanned = sscanf(&addr[i], "%hhu", &bytes[count]);
+        if (scanned < 1) {
+            return;
+        }
+
+        for (; addr[i] != '.'; i++) {
+            if (!addr[i]) {
+                return;
+            }
+        }
+
+        i++;
+    }
+}
+
+static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) {
+    int count = 0;
+    int i = 0;
+
+    for (; count < NSAPI_IPv6_BYTES/2; count++) {
+        int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
+        if (scanned < 1) {
+            return count;
+        }
+
+        for (; chunk[i] != ':'; i++) {
+            if (!chunk[i]) {
+                return count+1;
+            }
+        }
+
+        i++;
+    }
+
+    return count;
+}
+
+static void ipv6_from_address(uint8_t *bytes, const char *addr)
+{
+    // Start with zeroed address
+    uint16_t shorts[NSAPI_IPv6_BYTES/2];
+    memset(shorts, 0, sizeof shorts);
+
+    int suffix = 0;
+
+    // Find double colons and scan suffix
+    for (int i = 0; addr[i]; i++) {
+        if (addr[i] == ':' && addr[i+1] == ':') {
+            suffix = ipv6_scan_chunk(shorts, &addr[i+2]);
+            break;
+        }
+    }
+
+    // Move suffix to end
+    memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
+            suffix*sizeof(uint16_t));
+
+    // Scan prefix
+    ipv6_scan_chunk(shorts, &addr[0]);
+
+    // Flip bytes
+    for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
+        bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
+        bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
+    }
+}
+
+static void ipv4_to_address(char *addr, const uint8_t *bytes)
+{
+    sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]);
+}
+
+static void ipv6_to_address(char *addr, const uint8_t *bytes)
+{
+    for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
+        sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]);
+        addr[5*i+4] = ':';
+    }
+    addr[NSAPI_IPv6_SIZE-1] = '\0';
+}
+
+
+SocketAddress::SocketAddress(NetworkStack *iface, const char *host, uint16_t port)
+{
+    memset(&_ip_address, 0, sizeof _ip_address);
+
+    // Check for valid IP addresses
+    if (host && ipv4_is_valid(host)) {
+        _ip_version = NSAPI_IPv4;
+        ipv4_from_address(_ip_bytes, host);
+        set_port(port);
+    } else if (host && ipv6_is_valid(host)) {
+        _ip_version = NSAPI_IPv6;
+        ipv6_from_address(_ip_bytes, host);
+        set_port(port);
+    } else {
+        // DNS lookup
+        int err = iface->gethostbyname(this, host);
+        if (!err) {
+            set_port(port);
+        } else {
+            _ip_version = NSAPI_IPv4;
+            memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
+            set_port(0);
+        }
+    }
+}
+
+SocketAddress::SocketAddress(const char *addr, uint16_t port)
+{
+    memset(&_ip_address, 0, sizeof _ip_address);
+    set_ip_address(addr);
+    set_port(port);
+}
+
+SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port)
+{
+    memset(&_ip_address, 0, sizeof _ip_address);
+    set_ip_bytes(bytes, version);
+    set_port(port);
+}
+
+SocketAddress::SocketAddress(const SocketAddress &addr)
+{
+    memset(&_ip_address, 0, sizeof _ip_address);
+    set_ip_bytes(addr.get_ip_bytes(), addr.get_ip_version());
+    set_port(addr.get_port());
+}
+
+void SocketAddress::set_ip_address(const char *addr)
+{
+    _ip_address[0] = '\0';
+
+    if (addr && ipv4_is_valid(addr)) {
+        _ip_version = NSAPI_IPv4;
+        ipv4_from_address(_ip_bytes, addr);
+    } else if (addr && ipv6_is_valid(addr)) {
+        _ip_version = NSAPI_IPv6;
+        ipv6_from_address(_ip_bytes, addr);
+    } else {
+        _ip_version = NSAPI_IPv4;
+        memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
+    }
+}
+
+void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version)
+{
+    _ip_address[0] = '\0';
+
+    if (version == NSAPI_IPv4) {
+        _ip_version = NSAPI_IPv4;
+        memcpy(_ip_bytes, bytes, NSAPI_IPv4_BYTES);
+    } else if (version == NSAPI_IPv6) {
+        _ip_version = NSAPI_IPv6;
+        memcpy(_ip_bytes, bytes, NSAPI_IPv6_BYTES);
+    } else {
+        _ip_version = NSAPI_IPv4;
+        memset(_ip_bytes, 0, NSAPI_IPv4_BYTES);
+    }
+}
+
+void SocketAddress::set_port(uint16_t port)
+{
+    _port = port;
+}
+
+const char *SocketAddress::get_ip_address() const
+{
+    char *ip_address = (char *)_ip_address;
+
+    if (!ip_address[0]) {
+        if (_ip_version == NSAPI_IPv4) {
+            ipv4_to_address(ip_address, _ip_bytes);
+        } else if (_ip_version == NSAPI_IPv6) {
+            ipv6_to_address(ip_address, _ip_bytes);
+        }
+    }
+
+    return ip_address;
+}
+
+const void *SocketAddress::get_ip_bytes() const
+{
+    return _ip_bytes;
+}
+
+nsapi_version_t SocketAddress::get_ip_version() const
+{
+    return _ip_version;
+}
+
+uint16_t SocketAddress::get_port() const
+{
+    return _port;
+}
+
+SocketAddress::operator bool() const
+{
+    int count = 0;
+    if (_ip_version == NSAPI_IPv4) {
+        count = NSAPI_IPv4_BYTES;
+    } else if (_ip_version == NSAPI_IPv6) {
+        count = NSAPI_IPv6_BYTES;
+    }
+
+    for (int i = 0; i < count; i++) {
+        if (_ip_bytes[i]) {
+            return true;
+        }
+    }
+
+    return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/SocketAddress.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,166 @@
+/* SocketAddress
+ * 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 SOCKET_ADDRESS_H
+#define SOCKET_ADDRESS_H
+
+#include <stdint.h>
+
+
+/** Maximum size of IP address representation
+ */
+#define NSAPI_IP_SIZE NSAPI_IPv6_SIZE
+
+/** Maximum number of bytes for IP address
+ */
+#define NSAPI_IP_BYTES NSAPI_IPv6_BYTES
+
+/** Maximum size of MAC address representation
+ */
+#define NSAPI_MAC_SIZE 18
+
+/** Maximum number of bytes for MAC address
+ */
+#define NSAPI_MAC_BYTES 6
+
+/** Enum of IP address versions
+ *
+ *  The IP version specifies the type of an IP address.
+ *
+ *  @enum nsapi_version_t
+ */
+enum nsapi_version_t {
+    NSAPI_IPv4, /*!< Address is IPv4 */
+    NSAPI_IPv6, /*!< Address is IPv6 */
+};
+
+/** Size of IPv4 representation
+ */
+#define NSAPI_IPv4_SIZE 16
+
+/** Number of bytes in IPv4 address
+ */
+#define NSAPI_IPv4_BYTES 4
+
+/** Size of IPv6 representation
+ */
+#define NSAPI_IPv6_SIZE 40
+
+/** Number of bytes in IPv6 address
+ */
+#define NSAPI_IPv6_BYTES 16
+
+// Predeclared classes
+class NetworkStack;
+
+
+/** SocketAddress class
+ *
+ *  Representation of an IP address and port pair. 
+ */
+class SocketAddress {
+public:
+    /** Create a SocketAddress from a hostname and port
+     *
+     *  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.
+     *
+     *  On failure, the IP address and port will be set to zero
+     *  
+     *  @param iface    Network stack to use for DNS resolution
+     *  @param host     Hostname to resolve
+     *  @param port     Optional 16-bit port
+     */
+    SocketAddress(NetworkStack *iface, const char *host, uint16_t port = 0);
+
+    /** Create a SocketAddress from an IP address and port
+     *
+     *  @param host     Null-terminated representation of the IP address
+     *  @param port     Optional 16-bit port
+     */
+    SocketAddress(const char *addr = 0, uint16_t port = 0);
+
+    /** Create a SocketAddress from a raw IP address and port
+     *
+     *  @param bytes    Raw IP address in big-endian order
+     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     *  @param port     Optional 16-bit port
+     */
+    SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port = 0);
+
+    /** Create a SocketAddress from another SocketAddress
+     *
+     *  @param address  SocketAddress to copy
+     */
+    SocketAddress(const SocketAddress &addr);
+   
+    /** Set the IP address
+     *
+     *  @param addr     Null-terminated represention of the IP address
+     */
+    void set_ip_address(const char *addr);
+
+    /** Set the raw IP address
+     *
+     *  @param bytes    Raw IP address in big-endian order
+     *  @param version  IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     */
+    void set_ip_bytes(const void *bytes, nsapi_version_t version);
+
+    /** Set the port
+     *
+     *  @param port     16-bit port
+     */
+    void set_port(uint16_t port);
+    
+    /** Get the IP address
+     *
+     *  @return         Null-terminated representation of the IP Address
+     */
+    const char *get_ip_address() const;
+
+    /** Get the raw IP address
+     *
+     *  @return         Raw IP address in big-endian order
+     */
+    const void *get_ip_bytes() const;
+
+    /** Get the IP address version
+     *
+     *  @return         IP address version, NSAPI_IPv4 or NSAPI_IPv6
+     */
+    nsapi_version_t get_ip_version() const;
+    
+    /** Get the port
+     *
+     *  @return         The 16-bit port
+     */
+    uint16_t get_port() const;
+
+    /** Test if address is zero
+     *
+     *  @return         True if address is not zero
+     */
+    operator bool() const;
+
+private:
+    char _ip_address[NSAPI_IP_SIZE];
+    uint8_t _ip_bytes[NSAPI_IP_BYTES];
+    nsapi_version_t _ip_version;
+    uint16_t _port;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/TCPServer.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,75 @@
+/* Socket
+ * 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 "TCPServer.h"
+#include "Timer.h"
+
+TCPServer::TCPServer()
+{
+}
+
+TCPServer::TCPServer(NetworkStack *iface)
+{
+    open(iface);
+}
+
+int TCPServer::open(NetworkStack *iface)
+{
+    return Socket::open(iface, NSAPI_TCP);
+}
+
+int TCPServer::listen(int backlog)
+{
+    if (!_socket) {
+        return NSAPI_ERROR_NO_SOCKET;   
+    }
+
+    return _iface->socket_listen(_socket, backlog);
+}
+
+int TCPServer::accept(TCPSocket *connection)
+{
+    mbed::Timer timer;
+    timer.start();
+    mbed::Timeout timeout;
+    if (_timeout >= 0) {
+        timeout.attach_us(&Socket::wakeup, _timeout * 1000);
+    }
+
+    if (connection->_socket) {
+        connection->close();
+    }
+
+    while (true) {
+        if (!_socket) {
+            return NSAPI_ERROR_NO_SOCKET;   
+        }
+
+        void *socket;
+        int err = _iface->socket_accept(&socket, _socket);
+        if (!err) {
+            connection->_iface = _iface;
+            connection->_socket = socket;
+        }
+
+        if (err != NSAPI_ERROR_WOULD_BLOCK
+            || (_timeout >= 0 && timer.read_ms() >= _timeout)) {
+            return err;
+        }
+
+        __WFI();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/TCPServer.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,79 @@
+/* TCPServer
+ * 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 TCPSERVER_H
+#define TCPSERVER_H
+
+#include "Socket.h"
+#include "TCPSocket.h"
+#include "NetworkStack.h"
+
+/** TCP socket server
+  */
+class TCPServer : public Socket {
+public:
+    /** Create an uninitialized socket
+     *
+     *  Must call open to initialize the socket on a network stack.
+     */
+    TCPServer();
+
+    /** Create a socket on a network stack
+     *
+     *  Creates and opens a socket on the specified network stack.
+     *
+     *  @param iface    Network stack as target for socket
+     */
+    TCPServer(NetworkStack *iface);
+
+    /** Opens a socket
+     *
+     *  Creates a network socket on the specified network stack.
+     *  Not needed if stack is passed to the socket's constructor.
+     *
+     *  @param iface    Network stack as target for socket
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(NetworkStack *iface);
+    
+    /** Listen for connections on a TCP socket
+     *
+     *  Marks the socket as a passive socket that can be used to accept
+     *  incoming connections.
+     *
+     *  @param backlog  Number of pending connections that can be queued
+     *                  simultaneously, defaults to 1
+     *  @return         0 on success, negative error code on failure
+     */
+    int listen(int backlog = 1);
+    
+    /** Accepts a connection on a TCP socket
+     *
+     *  The server socket must be bound and set to listen for connections.
+     *  On a new connection, creates a network socket using the specified
+     *  socket instance.
+     *
+     *  By default, accept blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param socket   TCPSocket instance that will handle the incoming connection.
+     *  @return         0 on success, negative error code on failure
+     */
+    int accept(TCPSocket *connection);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/TCPSocket.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,100 @@
+/* Socket
+ * 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 "TCPSocket.h"
+#include "Timer.h"
+
+TCPSocket::TCPSocket(bool isTLS) : _isTLS(isTLS)
+{
+}
+
+TCPSocket::TCPSocket(NetworkStack *iface)
+{
+    open(iface);
+}
+
+int TCPSocket::open(NetworkStack *iface)
+{
+    return Socket::open(iface, _isTLS ? NSAPI_TLS : NSAPI_TCP);
+}
+
+int TCPSocket::connect(const SocketAddress &addr)
+{
+    if (!_socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    return _iface->socket_connect(_socket, addr);
+}
+
+
+int TCPSocket::connect(const char *host, uint16_t port)
+{
+    SocketAddress addr(_iface, host, port);
+    if (!addr) {
+        return NSAPI_ERROR_DNS_FAILURE;
+    }
+
+    return connect(addr);
+}
+
+int TCPSocket::send(const void *data, unsigned size)
+{
+    mbed::Timer timer;
+    timer.start();
+    mbed::Timeout timeout;
+    if (_timeout >= 0) {
+        timeout.attach_us(&Socket::wakeup, _timeout * 1000);
+    }
+
+    while (true) {
+        if (!_socket) {
+            return NSAPI_ERROR_NO_SOCKET;
+        }
+
+        int sent = _iface->socket_send(_socket, data, size);
+        if (sent != NSAPI_ERROR_WOULD_BLOCK
+            || (_timeout >= 0 && timer.read_ms() >= _timeout)) {
+            return sent;
+        }
+
+        __WFI();
+    }
+}
+
+int TCPSocket::recv(void *data, unsigned size)
+{
+    mbed::Timer timer;
+    timer.start();
+    mbed::Timeout timeout;
+    if (_timeout >= 0) {
+        timeout.attach_us(&Socket::wakeup, _timeout * 1000);
+    }
+
+    while (true) {
+        if (!_socket) {
+            return NSAPI_ERROR_NO_SOCKET;
+        }
+    
+        int recv = _iface->socket_recv(_socket, data, size);
+        if (recv != NSAPI_ERROR_WOULD_BLOCK
+            || (_timeout >= 0 && timer.read_ms() >= _timeout)) {
+            return recv;
+        }
+
+        __WFI();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/TCPSocket.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,110 @@
+/* TCPSocket
+ * 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 TCPSOCKET_H
+#define TCPSOCKET_H
+
+#include "Socket.h"
+#include "NetworkStack.h"
+
+/** TCP socket connection
+ */
+class TCPSocket : public Socket {
+public:
+    /** Create an uninitialized socket
+     *
+     *  Must call open to initialize the socket on a network stack.
+     */
+    TCPSocket(bool isTLS = false);
+
+    /** Create a socket on a network stack
+     *
+     *  Creates and opens a socket on the specified network stack.
+     *
+     *  @param iface    Network stack as target for socket
+     */
+    TCPSocket(NetworkStack *iface);
+
+    /** Opens a socket
+     *
+     *  Creates a network socket on the specified network stack.
+     *  Not needed if stack is passed to the socket's constructor.
+     *
+     *  @param iface    Network stack as target for socket
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(NetworkStack *iface);
+
+    /** Connects TCP socket to a remote host
+     *
+     *  Initiates a connection to a remote server specified by either
+     *  a domain name or an IP address and a port.
+     *
+     *  @param host     Hostname of the remote host
+     *  @param port     Port of the remote host
+     *  @return         0 on success, negative error code on failure
+     */
+    int connect(const char *host, uint16_t port);
+
+    /** Connects TCP socket to a remote host
+     *
+     *  Initiates a connection to a remote server specified by the
+     *  indicated address.
+     *
+     *  @param address  The SocketAddress of the remote host
+     *  @return         0 on success, negative error code on failure
+     */
+    int connect(const SocketAddress &address);
+    
+    /** Send data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes sent from the buffer.
+     *
+     *  By default, send blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    int send(const void *data, unsigned size);
+    
+    /** Receive data over a TCP socket
+     *
+     *  The socket must be connected to a remote host. Returns the number of
+     *  bytes received into the buffer.
+     *
+     *  By default, recv blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    int recv(void *data, unsigned size);
+
+private:
+    friend class TCPServer;
+
+    bool _isTLS;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/UDPSocket.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,90 @@
+/* Socket
+ * 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 "UDPSocket.h"
+#include "Timer.h"
+
+UDPSocket::UDPSocket()
+{
+}
+
+UDPSocket::UDPSocket(NetworkStack *iface)
+{
+    open(iface);
+}
+
+int UDPSocket::open(NetworkStack *iface)
+{
+    return Socket::open(iface, NSAPI_UDP);
+}
+
+int UDPSocket::sendto(const char *host, uint16_t port, const void *data, unsigned size)
+{
+    SocketAddress addr(_iface, host, port);
+    if (!addr) {
+        return NSAPI_ERROR_DNS_FAILURE;
+    }
+
+    return sendto(addr, data, size);
+}
+
+int UDPSocket::sendto(const SocketAddress &address, const void *data, unsigned size)
+{
+    mbed::Timer timer;
+    timer.start();
+    mbed::Timeout timeout;
+    if (_timeout >= 0) {
+        timeout.attach_us(&Socket::wakeup, _timeout * 1000);
+    }
+
+    while (true) {
+        if (!_socket) {
+            return NSAPI_ERROR_NO_SOCKET;
+        }
+    
+        int sent = _iface->socket_sendto(_socket, address, data, size);
+        if (sent != NSAPI_ERROR_WOULD_BLOCK
+            || (_timeout >= 0 && timer.read_ms() >= _timeout)) {
+            return sent;
+        }
+
+        __WFI();
+    }
+}
+
+int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size)
+{
+    mbed::Timer timer;
+    timer.start();
+    mbed::Timeout timeout;
+    if (_timeout >= 0) {
+        timeout.attach_us(&Socket::wakeup, _timeout * 1000);
+    }
+
+    while (true) {
+        if (!_socket) {
+            return NSAPI_ERROR_NO_SOCKET;
+        }
+    
+        int recv = _iface->socket_recvfrom(_socket, address, buffer, size);
+        if (recv != NSAPI_ERROR_WOULD_BLOCK
+            || (_timeout >= 0 && timer.read_ms() >= _timeout)) {
+            return recv;
+        }
+
+        __WFI();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/UDPSocket.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,105 @@
+/* UDPSocket
+ * 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 UDPSOCKET_H
+#define UDPSOCKET_H
+
+#include "Socket.h"
+#include "NetworkStack.h"
+
+/** UDP socket
+ */
+class UDPSocket : public Socket {
+public:
+    /** Create an uninitialized socket
+     *
+     *  Must call open to initialize the socket on a network stack.
+     */
+    UDPSocket();
+
+    /** Create a socket on a network stack
+     *
+     *  Creates and opens a socket on the specified network stack.
+     *
+     *  @param iface    Network stack as target for socket
+     */
+    UDPSocket(NetworkStack *iface);
+
+    /** Opens a socket
+     *
+     *  Creates a network socket on the specified network stack.
+     *  Not needed if stack is passed to the socket's constructor.
+     *
+     *  @param iface    Network stack as target for socket
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int open(NetworkStack *iface);
+
+    /** Send a packet over a UDP socket
+     *
+     *  Sends data to the specified address specified by either a domain name
+     *  or an IP address and port. Returns the number of bytes sent from the
+     *  buffer.
+     *
+     *  By default, sendto blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param host     Hostname of the remote host
+     *  @param port     Port of the remote host
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    int sendto(const char *host, uint16_t port, const void *data, unsigned size);
+
+    /** Send a packet over a UDP socket
+     *
+     *  Sends data to the specified address. Returns the number of bytes
+     *  sent from the buffer.
+     *
+     *  By default, sendto blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param address  The SocketAddress of the remote host
+     *  @param data     Buffer of data to send to the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of sent bytes on success, negative error
+     *                  code on failure
+     */
+    int sendto(const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet over a UDP socket
+     *
+     *  Receives data and stores the source address in address if address
+     *  is not NULL. Returns the number of bytes received into the buffer.
+     *
+     *  By default, recvfrom blocks until data is sent. If socket is set to
+     *  non-blocking or times out, NSAPI_ERROR_WOULD_BLOCK is returned
+     *  immediately.
+     *
+     *  @param address  Destination for the source address or NULL
+     *  @param data     Destination buffer for data received from the host
+     *  @param size     Size of the buffer in bytes
+     *  @return         Number of received bytes on success, negative error
+     *                  code on failure
+     */
+    int recvfrom(SocketAddress *address, void *data, unsigned size);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetworkSocketAPI/WiFiInterface.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,68 @@
+/* WiFiInterface
+ * 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 WIFI_INTERFACE_H
+#define WIFI_INTERFACE_H
+
+#include "NetworkStack.h"
+
+/** Enum of WiFi encryption types
+ *
+ *  The security type specifies a particular security to use when
+ *  connected to a WiFi network
+ *
+ *  @enum nsapi_protocol_t
+ */
+enum nsapi_security_t {
+    NSAPI_SECURITY_NONE = 0,   /*!< open access point */
+    NSAPI_SECURITY_WEP,        /*!< phrase conforms to WEP */
+    NSAPI_SECURITY_WPA,        /*!< phrase conforms to WPA */
+    NSAPI_SECURITY_WPA2,       /*!< phrase conforms to WPA2 */
+};
+
+/** WiFiInterface class
+ *
+ *  Common interface that is shared between WiFi devices
+ */
+class WiFiInterface
+{
+public:
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. If passphrase is invalid,
+     *  NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @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
+     *  @return          0 on success, negative error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 0;
+
+    /** Stop the interface
+     *
+     *  @return          0 on success, negative error code on failure
+     */
+    virtual int disconnect() = 0;
+
+    /** Get the local MAC address
+     *
+     *  @return         Null-terminated representation of the local MAC address
+     */
+    virtual const char *get_mac_address() = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/NOTICE.txt	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,7 @@
+This library is originated from: https://developer.mbed.org/teams/ST/code/X_NUCLEO_IDW01M1v2/#0368732b5b9d
+"class SpwfSAInterface" is extended with:
+ - method to setup WiFi module security parameters
+ - method to initiate hardware reset of WiFi module
+ - security socket support
+
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SPWF01SA/ATParser.lib	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ST/code/ATParser/#ea155e6b1fb1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SPWF01SA/NOTICE.txt	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,12 @@
+This library is originated from https://developer.mbed.org/teams/ST/code/SPWF01SA/#419285201dba
+It is extended with:
+	- TLS parameters setup
+	- Increased ATParser buffer size
+	- next wifi parameters are hardcoded to obtain higher robustness of WiFi Module:
+		* high-speed transfer mode is switched off
+		* operational rate is limited to 1 Mbit 
+		* basic data rates are limited to 802.11ab
+		* transmit power is forced to maximum
+		* power saving and sleep mode is switched off
+		* dhcp is forced to be switched on
+		* dhcp timeout is forced to 20 seconds
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SPWF01SA/SPWFSA01.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,492 @@
+/* SPWFInterface 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 "SPWFSA01.h"
+#include "mbed_debug.h"
+#include "stdint.h"
+
+#define SPWFSA01_CONNECT_TIMEOUT    15000
+#define SPWFSA01_SEND_TIMEOUT       500
+#define SPWFSA01_RECV_TIMEOUT       1500//some commands like AT&F/W takes some time to get the result back!
+#define SPWFSA01_MISC_TIMEOUT       500
+#define SPWFSA01_SOCKQ_TIMEOUT      3000
+
+#define EPOCH_TIME                  1453727657//Human time (GMT): Mon, 25 Jan 2016 13:14:17 GMT
+
+   SPWFSA01::SPWFSA01(PinName tx, PinName rx, PinName reset, PinName wakeup, bool debug)
+    : _serial(tx, rx, 1024), _parser(_serial,"\r\n", 2048),      
+      _wakeup(wakeup, PIN_OUTPUT, PullNone, 0),
+      _reset(reset, PIN_OUTPUT, PullNone, 1),
+      dbg_on(debug)
+{
+    _serial.baud(115200);  // LICIO  FIXME increase the speed
+    _parser.debugOn(debug);
+}
+
+bool SPWFSA01::startup(int mode)
+{
+    _parser.setTimeout(SPWFSA01_MISC_TIMEOUT);    
+    /*Test module before reset*/
+    waitSPWFReady();
+    /*Reset module*/
+    reset();
+     
+    /*set local echo to 0*/
+    if(!(_parser.send("AT+S.SCFG=localecho1,%d\r", 0) && _parser.recv("OK"))) 
+        {
+            debug_if(dbg_on, "SPWF> error local echo set\r\n");
+            return false;
+        }   
+    /*reset factory settings*/
+    if(!(_parser.send("AT&F") && _parser.recv("OK"))) 
+        {
+            debug_if(dbg_on, "SPWF> error AT&F\r\n");
+            return false;
+        }
+        
+    /*set Wi-Fi mode and rate to b/g*/
+    if(!(_parser.send("AT+S.SCFG=wifi_ht_mode,%d\r", 0) && _parser.recv("OK")))
+	{
+		debug_if(dbg_on, "SPWF> error setting ht_mode\r\n");
+		return false;
+	}
+        
+    //if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x003FFFCF\r") && _parser.recv("OK")))
+    if(!(_parser.send("AT+S.SCFG=wifi_opr_rate_mask,0x00000001\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+        {
+            debug_if(dbg_on, "SPWF> error setting operational rates\r\n");
+            return false;
+        }
+
+    if(!(_parser.send("AT+S.SCFG=wifi_bas_rate_mask,0x0000000F\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+		debug_if(dbg_on, "SPWF> error setting basic rates\r\n");
+		return false;
+	}
+
+    if(!(_parser.send("AT+S.SCFG=wifi_powersave,0\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+	   debug_if(dbg_on, "SPWF> error setting power save mode\r\n");
+	   return false;
+	}
+
+    if(!(_parser.send("AT+S.SCFG=sleep_enabled,0\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+	   debug_if(dbg_on, "SPWF> error setting sleep  mode\r\n");
+	   return false;
+	}
+
+    if(!(_parser.send("AT+S.SCFG=wifi_tx_power,18\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+	   debug_if(dbg_on, "SPWF> error setting transmit power\r\n");
+	   return false;
+	}
+
+    if(!(_parser.send("AT+S.SCFG=ip_use_dhcp,1\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+	   debug_if(dbg_on, "SPWF> error setting dhcp on\r\n");
+	   return false;
+	}
+
+    if(!(_parser.send("AT+S.SCFG=ip_dhcp_timeout,20\r") && _parser.recv("OK")))// set most effective speed for such kind of device
+	{
+	   debug_if(dbg_on, "SPWF> error setting dhcp timeout\r\n");
+	   return false;
+	}
+
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", mode) && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
+            return false;
+        } 
+
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error AT&W\r\n");
+            return false;
+        }
+        
+    /*reset again and send AT command and check for result (AT->OK)*/
+    reset();
+        
+    return true;    
+}
+
+bool SPWFSA01::hw_reset(void)
+{    
+    if (_reset.is_connected()) {
+    /* reset the pin PC12 */  
+    _reset.write(0);
+    wait_ms(200);
+    _reset.write(1); 
+    wait_ms(100);
+    return 1;
+    } else { return 0; }
+}
+
+bool SPWFSA01::reset(void)
+{
+    if(!_parser.send("AT+CFUN=1")) return false;
+    while(1) {
+        if (_parser.recv("+WIND:32:WiFi Hardware Started\r")) {
+            return true;
+        }
+    }
+}
+
+void SPWFSA01::waitSPWFReady(void)
+{
+    //wait_ms(200);
+    while(1) 
+        if(_parser.send("AT") && _parser.recv("OK"))
+            //till we get OK from AT command
+            //printf("\r\nwaiting for reset to complete..\n");
+            return;
+                 
+}
+
+/* Security Mode
+    None          = 0, 
+    WEP           = 1,
+    WPA_Personal  = 2,
+*/
+bool SPWFSA01::connect(const char *ap, const char *passPhrase, int securityMode)
+{
+    uint32_t n1, n2, n3, n4;
+
+    _parser.setTimeout(SPWFSA01_CONNECT_TIMEOUT);       
+    //AT+S.SCFG=wifi_wpa_psk_text,%s\r
+    if(!(_parser.send("AT+S.SCFG=wifi_wpa_psk_text,%s", passPhrase) && _parser.recv("OK"))) 
+        {
+            debug_if(dbg_on, "SPWF> error pass set\r\n");
+            return false;
+        } 
+    //AT+S.SSIDTXT=%s\r
+    if(!(_parser.send("AT+S.SSIDTXT=%s", ap) && _parser.recv("OK"))) 
+        {
+            debug_if(dbg_on, "SPWF> error ssid set\r\n");
+            return false;
+        }
+    //AT+S.SCFG=wifi_priv_mode,%d\r
+    if(!(_parser.send("AT+S.SCFG=wifi_priv_mode,%d", securityMode) && _parser.recv("OK"))) 
+        {
+            debug_if(dbg_on, "SPWF> error security mode set\r\n");
+            return false;
+        } 
+    //"AT+S.SCFG=wifi_mode,%d\r"
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 1) && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
+            return false;
+        }
+    //AT&W
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error AT&W\r\n");
+            return false;
+        }
+    //reset module
+    reset();
+    
+    while(1)
+        if((_parser.recv("+WIND:24:WiFi Up:%u.%u.%u.%u",&n1, &n2, &n3, &n4)))
+            {
+                break;
+            }            
+        
+    return true;
+}
+
+bool SPWFSA01::disconnect(void)
+{
+    //"AT+S.SCFG=wifi_mode,%d\r"
+    /*set idle mode (0->idle, 1->STA,3->miniAP, 2->IBSS)*/
+    if(!(_parser.send("AT+S.SCFG=wifi_mode,%d\r", 0) && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error wifi mode set\r\n");
+            return false;
+        }
+    //AT&W
+    /* save current setting in flash */
+    if(!(_parser.send("AT&W") && _parser.recv("OK")))
+        {
+            debug_if(dbg_on, "SPWF> error AT&W\r\n");
+            return false;
+        }
+    //reset module
+    reset();
+    return true;
+}
+
+bool SPWFSA01::dhcp(int mode)
+{
+    //only 3 valid modes
+    //0->off(ip_addr must be set by user), 1->on(auto set by AP), 2->on&customize(miniAP ip_addr can be set by user)
+    if(mode < 0 || mode > 2) {
+        return false;
+    }
+        
+    return _parser.send("AT+S.SCFG=ip_use_dhcp,%d\r", mode)
+        && _parser.recv("OK");
+}
+
+
+const char *SPWFSA01::getIPAddress(void)
+{
+    uint32_t n1, n2, n3, n4;
+    
+    if (!(_parser.send("AT+S.STS=ip_ipaddr")
+        && _parser.recv("#  ip_ipaddr = %u.%u.%u.%u", &n1, &n2, &n3, &n4)
+        && _parser.recv("OK"))) {
+            debug_if(dbg_on, "SPWF> getIPAddress error\r\n");
+        return 0;
+    }
+
+    sprintf((char*)_ip_buffer,"%u.%u.%u.%u", n1, n2, n3, n4);
+
+    return _ip_buffer;
+}
+
+const char *SPWFSA01::getMACAddress(void)
+{
+    uint32_t n1, n2, n3, n4, n5, n6;
+    
+    if (!(_parser.send("AT+S.GCFG=nv_wifi_macaddr")
+        && _parser.recv("#  nv_wifi_macaddr = %x:%x:%x:%x:%x:%x", &n1, &n2, &n3, &n4, &n5, &n6)
+        && _parser.recv("OK"))) {
+            debug_if(dbg_on, "SPWF> getMACAddress error\r\n");
+        return 0;
+    }
+
+    sprintf((char*)_mac_buffer,"%02X:%02X:%02X:%02X:%02X:%02X", n1, n2, n3, n4, n5, n6);
+
+    return _mac_buffer;
+}
+
+bool SPWFSA01::isConnected(void)
+{
+    return getIPAddress() != 0; 
+}
+
+bool SPWFSA01::open(const char *type, int* id, const char* addr, int port)
+{
+    Timer timer;
+    timer.start();
+    socket_closed = 0; 
+       
+    if(!_parser.send("AT+S.SOCKON=%s,%d,%s,ind", addr, port, type))
+        {
+            debug_if(dbg_on, "SPWF> error opening socket\r\n");
+            return false;
+        }
+        
+    while(1)
+        {
+            if( _parser.recv(" ID: %d", id)
+                && _parser.recv("OK"))
+                break;
+            
+            if (timer.read_ms() > SPWFSA01_CONNECT_TIMEOUT) {
+                return false;
+            }
+        
+            //TODO:implement time-out functionality in case of no response
+            //if(timeout) return false;
+            //TODO: deal with errors like "ERROR: Failed to resolve name"
+            //TODO: deal with errors like "ERROR: Data mode not available"
+        }
+
+    return true;
+}
+
+bool SPWFSA01::send(int id, const void *data, uint32_t amount)
+{    
+    char _buf[18];
+    _parser.setTimeout(SPWFSA01_SEND_TIMEOUT);
+    
+    sprintf((char*)_buf,"AT+S.SOCKW=%d,%d\r", id, amount);   
+    
+    //May take a second try if device is busy
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.write((char*)_buf, strlen(_buf)) >=0
+            && _parser.write((char*)data, (int)amount) >= 0
+            && _parser.recv("OK")) {
+            return true;
+        }     
+    }
+    return false;
+}
+
+
+int32_t SPWFSA01::recv(int id, void *data, uint32_t amount)
+{
+    uint32_t recv_amount=0;
+    int wind_id;    
+ 
+    if (socket_closed) {
+        socket_closed = 0;
+        return -3;
+    }
+    if(!(_parser.send("AT+S.SOCKQ=%d", id)  //send a query (will be required for secure sockets)
+        && _parser.recv(" DATALEN: %u", &recv_amount)
+        && _parser.recv("OK"))) {
+        return -2;
+    }            
+    if (recv_amount==0) { return -1; } 
+    if(recv_amount > amount)
+        recv_amount = amount;
+        
+    int par_timeout = _parser.getTimeout();        
+    _parser.setTimeout(0);
+    
+     while(_parser.recv("+WIND:%d:", &wind_id)) {
+//        printf("Wind received: %d\n\r", wind_id);
+        if (wind_id == 58) {
+            socket_closed = 1;
+            _parser.flush();            
+        }
+    }       
+    _parser.setTimeout(par_timeout);
+    
+    _parser.flush();
+    if(!(_parser.send("AT+S.SOCKR=%d,%d", id, recv_amount))){
+        return -2;    
+    }
+    if(!((_parser.read((char*)data, recv_amount) >0)
+            && _parser.recv("OK"))) {
+        return -2;
+    }    
+    return recv_amount;
+}
+
+bool SPWFSA01::close(int id)
+{
+    uint32_t recv_amount=0;    
+    void * data = NULL;    
+
+    _parser.setTimeout(SPWFSA01_MISC_TIMEOUT);    
+    _parser.flush();
+    /* socket flush */
+    if(!(_parser.send("AT+S.SOCKQ=%d", id)  //send a query (will be required for secure sockets)
+        && _parser.recv(" DATALEN: %u", &recv_amount)
+        && _parser.recv("OK"))) {
+            return -2;
+    } 
+    if (recv_amount>0) {
+        data = malloc (recv_amount+4);
+        if(!(_parser.send("AT+S.SOCKR=%d,%d", id, recv_amount))) { 
+            free (data); 
+            return -2; 
+        }
+ //       printf ("--->>>Close flushing recv_amount: %d  \n\r",recv_amount);            
+        if(!((_parser.read((char*)data, recv_amount) >0)
+            && _parser.recv("OK"))) {
+             free (data);
+             return -2;
+        }
+        free (data);                            
+    }     
+    
+    //May take a second try if device is busy or error is returned
+    for (unsigned i = 0; i < 2; i++) {
+        if (_parser.send("AT+S.SOCKC=%d", id)
+            && _parser.recv("OK")) {
+            socket_closed = 1;     
+            return true;
+        }
+        else
+        {
+            if(_parser.recv("ERROR: Pending data")) {
+                    debug_if(dbg_on, "SPWF> ERROR!!!!\r\n");
+                    return false;
+            }
+        }
+        //TODO: Deal with "ERROR: Pending data" (Closing a socket with pending data)
+    }
+    return false;
+}
+
+
+bool SPWFSA01::readable()
+{
+    return _serial.readable();
+}
+
+bool SPWFSA01::writeable()
+{
+    return _serial.writeable();
+}
+
+int SPWFSA01::setSocketClientSecurity(uint8_t* tls_mode, uint8_t* root_ca_server, uint8_t* client_cert, uint8_t* client_key, uint8_t* client_domain, uint32_t tls_epoch_time)
+{
+	int err = 0;
+	unsigned long epoch_time;
+
+	if(!(_parser.send("AT+S.TLSCERT2=clean,all\r", 0) && _parser.recv("OK")))
+	{
+	  debug_if(dbg_on, "SPWF> TLSCERT2 cleared\r\n");
+	  return -1;
+	}
+
+	if(tls_epoch_time==0)
+		epoch_time = EPOCH_TIME;
+	else
+		epoch_time = tls_epoch_time;
+
+	if(!(_parser.send("AT+S.SETTIME=%lu\r", (unsigned long)epoch_time) && _parser.recv("OK")))
+	{
+	  debug_if(dbg_on, "SPWF> time is set to %d\r\n", epoch_time);
+	  return -1;
+	}
+
+	/*AT+S.TLSCERT=f_ca,<size><CR><data>*/
+	if(!(_parser.send("AT+S.TLSCERT=f_ca,%d\r%s\r", strlen((const char *)root_ca_server) - 1, root_ca_server) && _parser.recv("OK")))
+	{
+	  debug_if(dbg_on, "SPWF> error TLSCERT=f_ca set\r\n");
+	  return -1;
+	}
+
+	/*AT+S.TLSCERT=f_cert,<size><CR><data>*/
+	if(tls_mode[0]=='m')
+	{
+		if(!(_parser.send("AT+S.TLSCERT=f_cert,%d\r%s", strlen((const char *)client_cert) - 1, client_cert) && _parser.recv("OK")))
+		{
+		  debug_if(dbg_on, "SPWF> error TLSCERT=f_cert set\r\n");
+		  return -1;
+		}
+
+	    /*AT+S.TLSCERT=f_key,<size><CR><data>*/
+	    if(!(_parser.send("AT+S.TLSCERT=f_key,%d\r%s", strlen((const char *)client_key) - 1, client_key) && _parser.recv("OK")))
+		{
+		  debug_if(dbg_on, "SPWF> error TLSCERT=f_key set\r\n");
+		  return -1;
+		}
+	}
+
+	/*AT+S.TLSDOMAIN=f_domain,<server domain>*/
+	if(!(_parser.send("AT+S.TLSDOMAIN=f_domain,%s\r", client_domain) && _parser.recv("OK")))
+	{
+	  debug_if(dbg_on, "SPWF> error TLSDOMAIN=f_domain set\r\n");
+	  return -1;
+	}
+
+	return err;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SPWF01SA/SPWFSA01.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,168 @@
+/* SPWFInterface 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 SPWFSA01_H
+#define SPWFSA01_H
+ 
+#include "ATParser.h"
+ 
+/** SPWFSA01Interface class.
+    This is an interface to a SPWFSA01 module.
+ */
+class SPWFSA01
+{
+public:
+    
+    SPWFSA01(PinName tx, PinName rx, PinName reset=NC, PinName wakeup=NC, bool debug=false);
+    
+    /**
+    * Init the SPWFSA01
+    *
+    * @param mode mode in which to startup
+    * @return true only if SPWFSA01 has started up correctly
+    */
+    bool startup(int mode);
+ 
+    void waitSPWFReady(void);
+    /**
+    * Reset SPWFSA01
+    *
+    * @return true only if SPWFSA01 resets successfully
+    */
+    bool reset(void);
+    
+    bool hw_reset(void);
+ 
+    /**
+    * Enable/Disable DHCP
+    *
+    * @param mode mode of DHCP 2-softAP, 1-on, 0-off
+    * @return true only if SPWFSA01 enables/disables DHCP successfully
+    */
+    bool dhcp(int mode);
+ 
+    /**
+    * Connect SPWFSA01 to AP
+    *
+    * @param ap the name of the AP
+    * @param passPhrase the password of AP
+    * @param securityMode the security mode of AP (WPA/WPA2, WEP, Open)
+    * @return true only if SPWFSA01 is connected successfully
+    */
+    bool connect(const char *ap, const char *passPhrase, int securityMode);
+ 
+    /**
+    * Disconnect SPWFSA01 from AP
+    *
+    * @return true only if SPWFSA01 is disconnected successfully
+    */
+    bool disconnect(void);
+ 
+    /**
+    * Get the IP address of SPWFSA01
+    *
+    * @return null-teriminated IP address or null if no IP address is assigned
+    */
+    const char *getIPAddress(void);
+ 
+    /**
+    * Get the MAC address of SPWFSA01
+    *
+    * @return null-terminated MAC address or null if no MAC address is assigned
+    */
+    const char *getMACAddress(void);
+ 
+    /**
+    * Check if SPWFSA01 is conenected
+    *
+    * @return true only if the chip has an IP address
+    */
+    bool isConnected(void);
+
+    /**
+    * @brief  wifi_socket_client_security
+    *         Set the security certificates and key for secure socket (TLS)
+    * @param  None
+    * @retval return nonzero in case of error
+    */
+    int setSocketClientSecurity(uint8_t* tls_mode, uint8_t* root_ca_server, uint8_t* client_cert, uint8_t* client_key, uint8_t* client_domain, uint32_t tls_epoch_time);
+ 
+    /**
+    * Open a socketed connection
+    *
+    * @param type the type of socket to open "u" (UDP) or "t" (TCP)
+    * @param id id to get the new socket number, valid 0-7
+    * @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);
+ 
+ 
+    /**
+    * Checks if data is available
+    */
+    bool readable();
+ 
+    /**
+    * Checks if data can be written
+    */
+    bool writeable();
+ 
+private:
+    BufferedSerial _serial;
+    ATParser _parser;
+    DigitalInOut _wakeup;
+    DigitalInOut _reset; 
+    char _ip_buffer[16];
+    char _mac_buffer[18];
+    bool dbg_on;
+//    int _timeout; // FIXME LICIO we have "virtual" socket tmo, module socket tmo, 
+// AT parser tmo, recv/send tmo, actually used the NetworksocketAPI socket tmo
+    unsigned int _recv_timeout; // see SO_RCVTIMEO setsockopt
+    unsigned int _send_timeout; // see SO_SNDTIMEO setsockopt   
+    unsigned int socket_closed;
+};
+ 
+#endif  //SPWFSA01_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SpwfInterface.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,464 @@
+/* mbed Microcontroller Library
+* Copyright (c) 20015 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.
+*/
+
+/**
+  ******************************************************************************
+  * @file    SpwfInterface.cpp 
+  * @author  STMicroelectronics
+  * @brief   Implementation of the NetworkStack for the SPWF Device
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+  
+#include "SpwfInterface.h"
+ 
+// Various timeouts for different SPWF operations
+#define SPWF_CONNECT_TIMEOUT 20000
+#define SPWF_SEND_TIMEOUT    500
+#define SPWF_RECV_TIMEOUT    500
+#define SPWF_MISC_TIMEOUT    15000
+
+/** spwf_socket class
+ *  Implementation of SPWF socket structure
+ */
+struct spwf_socket {
+    int id;
+    int server_port;
+    nsapi_protocol_t proto;
+    bool connected;
+};
+
+
+/**
+* @brief  SpwfSAInterface constructor         
+* @param  tx: Pin USART TX  
+*         rx: Pin USART RX
+*         rst: reset pin for Spwf module
+*         wkup: reset pin for Spwf module
+*         rts: Pin USART RTS
+*         debug : not used
+* @retval none
+*/
+SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx, bool debug)     
+    : _spwf(tx, rx, PC_12, PC_8, debug)
+{
+    memset(_ids, 0, sizeof(_ids));
+    isInitialized = false;
+    isListening = false;    
+}
+
+SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx, PinName reset, PinName wakeup, bool debug)
+    : _spwf(tx, rx, reset, wakeup, debug)
+{
+    memset(_ids, 0, sizeof(_ids));
+    isInitialized = false;
+    isListening = false;
+}    
+
+/**
+* @brief  SpwfSAInterface destructor         
+* @param  none
+* @retval none
+*/
+SpwfSAInterface::~SpwfSAInterface()
+{
+}
+
+/**
+* @brief  init function
+          initializes SPWF FW and module         
+* @param  none
+* @retval error value
+*/
+int SpwfSAInterface::init(void) 
+{
+    if(_spwf.startup(0)) {
+        isInitialized=true;
+        return true;
+    }
+    else return NSAPI_ERROR_DEVICE_ERROR;
+}
+
+/**
+* @brief  network connect
+          connects to Access Point
+* @param  ap: Access Point (AP) Name String  
+*         pass_phrase: Password String for AP
+*         security: type of NSAPI security supported
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::connect(const char *ap, 
+                             const char *pass_phrase, 
+                             nsapi_security_t security)
+{    
+    int mode;
+    
+    //initialize the device before connecting
+    if(!isInitialized)
+    {
+        if(!init())
+            return NSAPI_ERROR_DEVICE_ERROR;
+    }
+   
+    switch(security)
+    {
+        case NSAPI_SECURITY_NONE:
+            mode = 0;
+            pass_phrase = NULL;
+            break;
+        case NSAPI_SECURITY_WEP:
+            mode = 1;
+            break;
+        case NSAPI_SECURITY_WPA:
+        case NSAPI_SECURITY_WPA2:
+            mode = 2;
+            break;
+        default:
+            mode = 2;
+            break;
+    }
+    return (_spwf.connect((char*)ap, (char*)pass_phrase, mode));
+}
+
+/**
+* @brief  network disconnect
+          disconnects from Access Point
+* @param  none
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::disconnect()
+{    
+    return (_spwf.disconnect());
+}
+
+/** 
+* @brief  Get the local IP address
+* @param  none
+* @retval Null-terminated representation of the local IP address
+*         or null if not yet connected
+*/
+const char *SpwfSAInterface::get_ip_address()
+{
+    return _spwf.getIPAddress();
+}
+
+/** 
+* @brief  Get the MAC address
+* @param  none
+* @retval Null-terminated representation of the MAC address
+*         or null if not yet connected
+*/
+const char *SpwfSAInterface::get_mac_address()
+{
+    return _spwf.getMACAddress();
+}
+
+/**
+* @brief  open a socket handle
+* @param  handle: Pointer to handle
+*         proto: TCP/UDP protocol
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    int id = -1;    
+
+    struct spwf_socket *socket = new struct spwf_socket; 
+    if (!socket) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    socket->id = id;
+    socket->server_port = id;
+    socket->proto = proto;
+    socket->connected = false;
+    *handle = socket;
+    return 0;
+}
+
+/**
+* @brief  connect to a remote socket
+* @param  handle: Pointer to socket handle
+*         addr: Address to connect to
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    int sock_id = 99;
+    struct spwf_socket *socket = (struct spwf_socket *)handle;
+    const char *proto;
+    
+    switch (socket->proto)
+    {
+    	case NSAPI_UDP:
+    			proto = "u";
+    		break;
+
+    	case NSAPI_TCP:
+    			proto = "t";
+    		break;
+
+    	case NSAPI_TLS:
+    	    	proto = "s";
+    	    break;
+    	default:
+    			return NSAPI_ERROR_UNSUPPORTED;
+    		break;// defensive programming
+    }
+
+    if (!_spwf.open(proto, &sock_id, addr.get_ip_address(), addr.get_port())) {;//sock ID is allocated NOW
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    
+    //TODO: Maintain a socket table to map socket ID to host & port
+    //TODO: lookup on client table to see if already socket is allocated to same host/port
+    //multimap <char *, vector <uint16_t> > ::iterator i = c_table.find((char*)ip);
+      
+    if(sock_id <= SPWFSA_SOCKET_COUNT)
+    {
+        socket->id = sock_id;//the socket ID of this Socket instance
+        _ids[socket->id] = true;
+        socket->connected = true;
+    }
+    else 
+        return NSAPI_ERROR_NO_SOCKET;
+    
+    return 0;
+}
+
+/**
+* @brief  bind to a port number and address
+* @param  handle: Pointer to socket handle
+*         proto: address to bind to
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address)
+{
+    struct spwf_socket *socket = (struct spwf_socket *)handle;    
+    socket->server_port = address.get_port();
+    return 0;
+}
+
+/**
+* @brief  start listening on a port and address
+* @param  handle: Pointer to handle
+*         backlog: not used (always value is 1)
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_listen(void *handle, int backlog)
+{      
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+/**
+* @brief  accept connections from remote sockets
+* @param  handle: Pointer to handle of client socket (connecting)
+*         proto: handle of server socket which will accept connections
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_accept(void **handle, void *server)
+{    
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+/**
+* @brief  close a socket
+* @param  handle: Pointer to handle
+* @retval NSAPI Error Type
+*/
+int SpwfSAInterface::socket_close(void *handle)
+{
+    struct spwf_socket *socket = (struct spwf_socket *)handle;
+    int err = 0;
+    
+    if(socket->id!=-1)
+    {
+        if (_spwf.close(socket->id)) {
+            if(socket->id==SERVER_SOCKET_NO)      
+                isListening = false;
+            else
+                _ids[socket->id] = false;            
+        }
+        else err = NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    delete socket;
+    return err;
+}
+
+/**
+* @brief  write to a socket
+* @param  handle: Pointer to handle
+*         data: pointer to data
+*         size: size of data
+* @retval no of bytes sent
+*/
+int SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size)
+{    
+    struct spwf_socket *socket = (struct spwf_socket *)handle;
+    //int err;
+    
+    /*if(socket->id==SERVER_SOCKET_NO)
+        {
+            if(socket->server_port==-1 || !isListening) 
+                return NSAPI_ERROR_NO_SOCKET; //server socket not bound or not listening        
+
+            err = _spwf.socket_server_write((uint16_t)size, (char*)data);
+        }
+    else
+        {
+            err = _spwf.send(socket->id, (char*)data, (uint32_t)size);
+        }*/
+    if (!_spwf.send(socket->id, (char*)data, (uint32_t)size)) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+ 
+    return size;
+}
+
+/**
+* @brief  receive data on a socket
+* @param  handle: Pointer to handle
+*         data: pointer to data
+*         size: size of data
+* @retval no of bytes read
+*/
+int SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size)
+{
+    struct spwf_socket *socket = (struct spwf_socket *)handle;
+    int32_t recv;
+    
+    //CHECK:Receive for both Client and Server Sockets same?
+    recv = _spwf.recv(socket->id, (char*)data, (uint32_t)size);    
+    if (recv < 0) {
+        //wait_ms(1);//delay of 1ms <for F4>??
+        //printf(".");
+        if (recv == -1) return NSAPI_ERROR_WOULD_BLOCK;//send this if we want to block call (else timeout will happen)
+        else if (recv == -2)return NSAPI_ERROR_DEVICE_ERROR;
+        else if (recv == -3)return NSAPI_ERROR_NO_CONNECTION;
+    }
+    return recv;    
+}
+
+/**
+* @brief  send data to a udp socket
+* @param  handle: Pointer to handle
+*         addr: address of udp socket
+*         data: pointer to data
+*         size: size of data
+* @retval no of bytes sent
+*/
+int SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    struct spwf_socket *socket = (struct spwf_socket *)handle;
+    if (!socket->connected) {  
+        int err = socket_connect(socket, addr);
+        if (err < 0) {
+            return err;
+        }
+    }
+    
+    return socket_send(socket, data, size);
+}
+
+/**
+* @brief  receive data on a udp socket
+* @param  handle: Pointer to handle
+*         addr: address of udp socket
+*         data: pointer to data
+*         size: size of data
+* @retval no of bytes read
+*/
+int SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    struct spwf_socket *socket = (struct spwf_socket *)handle;    
+    return socket_recv(socket, data, size);
+}
+
+/**
+* @brief  attach function/callback to the socket
+*         Not used
+* @param  handle: Pointer to handle
+*         callback: callback function pointer
+*         data: pointer to data
+* @retval none
+*/
+void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
+{
+    //No implementation yet
+}
+
+/**
+* @brief  utility debug function for printing to serial terminal
+* @param  string: Pointer to data
+* @retval none
+*/
+void SpwfSAInterface::debug(const char * string)
+{
+    //_spwf.debug_print(string);
+}
+
+/**
+* @brief  Set the socket options
+*         Not used
+* @param  handle: Pointer to handle         
+*         level:  SOL_SOCKET
+*         optname: option name
+*         optval:  pointer to option value
+*         optlen:  option length
+@retval NSAPI Error Type
+*/
+int SpwfSAInterface::setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen)
+{
+//    struct spwf_socket *socket = (struct spwf_socket *)handle;      
+    
+    switch (optname) {
+            case NSAPI_REUSEADDR: /*!< Allow bind to reuse local addresses */
+            case NSAPI_KEEPALIVE: /*!< Enables sending of keepalive messages */
+            case NSAPI_LINGER:    /*!< Keeps close from returning until queues empty */
+            case NSAPI_SNDBUF:    /*!< Sets send buffer size */
+            case NSAPI_RCVBUF:    /*!< Sets recv buffer size */               
+      default:
+           printf("SpwfSAInterface::setsockopt> ERROR!!!! Unknown optname: %d \r\n", optname);
+           return -1;        
+    }
+    return NSAPI_ERROR_UNSUPPORTED;// defensive programming
+}
+    
+/**
+* @brief  Get the socket options
+*         Not used
+* @param  handle: Pointer to handle         
+*         level: SOL_SOCKET
+*         optname: option name
+*         optval:  pointer to option value
+*         optlen:  pointer to option length
+@retval NSAPI Error Type
+*/
+int SpwfSAInterface::getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen)    
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IDW01M1v2/SpwfInterface.h	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,99 @@
+/* mbed Microcontroller Library
+* Copyright (c) 20015 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.
+*/
+
+/**
+  ******************************************************************************
+  * @file    SpwfInterface.h 
+  * @author  STMicroelectronics
+  * @brief   Header file of the NetworkStack for the SPWF Device
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */
+  
+#ifndef SPWFSA_INTERFACE_H
+#define SPWFSA_INTERFACE_H
+
+#include "WiFiInterface.h"
+#include "SPWFSA01.h"
+ 
+#define SPWFSA_SOCKET_COUNT 8
+#define SERVER_SOCKET_NO    9
+ 
+/** SpwfSAInterface class
+ *  Implementation of the NetworkStack for the SPWF Device
+ */
+class SpwfSAInterface : public NetworkStack, public WiFiInterface
+{
+public:
+    SpwfSAInterface(PinName tx, PinName rx, bool debug);
+    SpwfSAInterface(PinName tx, PinName rx, PinName reset = PC_12, PinName wakeup = PC_8, bool debug = false);    
+    virtual     ~SpwfSAInterface();
+ 
+    // Implementation of WiFiInterface
+    virtual     int connect(const char *ssid,
+                            const char *pass,
+                            nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    inline int setSocketClientSecurity(uint8_t* tls_mode, uint8_t* root_ca_server, uint8_t* client_cert, uint8_t* client_key, uint8_t* client_domain, uint32_t tls_epoch_time)
+    {
+    	return _spwf.setSocketClientSecurity(tls_mode, root_ca_server, client_cert, client_key, client_domain, tls_epoch_time);
+    }
+ 
+    virtual     int disconnect();    
+    virtual     const char *get_mac_address();    
+    void        debug(const char * string);
+    inline bool	    reset_chip() {return _spwf.hw_reset();};
+    
+    //Implementation of NetworkStack
+    virtual     const char *get_ip_address();
+    
+protected:
+    //Implementation of NetworkStack
+    virtual     int socket_open(void **handle, nsapi_protocol_t proto);    
+    virtual     int socket_close(void *handle);    
+    virtual     int socket_bind(void *handle, const SocketAddress &address);  //not supported  
+    virtual     int socket_listen(void *handle, int backlog);
+    virtual     int socket_connect(void *handle, const SocketAddress &address);
+    virtual     int socket_accept(void **handle, void *server);
+    virtual     int socket_send(void *handle, const void *data, unsigned size);  
+    virtual     int socket_recv(void *handle, void *data, unsigned size);    
+    virtual     int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);    
+    virtual     int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);    
+    virtual     void socket_attach(void *handle, void (*callback)(void *), void *data);
+    virtual     int setsockopt(void *handle, int level, int optname, const void *optval, unsigned optlen);    
+    virtual     int getsockopt(void *handle, int level, int optname, void *optval, unsigned *optlen);    
+           
+private:
+    int         init(void);
+        
+    SPWFSA01 _spwf;
+    bool _ids[SPWFSA_SOCKET_COUNT];
+    bool isListening;
+    bool isInitialized;
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IKS01A1.lib	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ST/code/X_NUCLEO_IKS01A1/#d17ab29129ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,399 @@
+/* SpwfInterface NetworkSocketAPI Example Program
+ * Copyright (c) 2015 ARM Limited
+ * Copyright (c) 2017 KLIKA TECH, LLC
+ *
+ * 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.
+ 
+ Contributors:
+  *    Klika Tech - completely adopted to Amazon AWS IoT service
+
+ */
+
+#include "mbed.h"
+#include "SpwfInterface.h"
+#include "TCPSocket.h"
+#include "MQTTClient.h"
+#include "MQTTWiFi.h"
+#include <ctype.h>
+#include "x_nucleo_iks01a1.h"
+
+//------------------------------------
+// Hyperterminal default configuration
+// 9600 bauds, 8-bit data, no parity
+//------------------------------------
+Serial pc(SERIAL_TX, SERIAL_RX); 
+DigitalOut myled(LED2);
+DigitalOut butled(LED3);
+InterruptIn  mybutton(USER_BUTTON);
+
+bool myButtonPressed = false;
+    
+#define MQTT_MAX_PACKET_SIZE 350
+#define MQTT_MAX_PAYLOAD_SIZE 300 
+
+#define AWS_IOT_MQTT_HOST              "xxxxxxxxxx.iot.us-east-1.amazonaws.com" //Use your own host.
+#define AWS_IOT_MQTT_PORT              8883
+#define AWS_IOT_MQTT_CLIENT_ID         "Nucleo" //Should be kept if you are using same device clent.
+#define AWS_IOT_MY_THING_NAME          "Nucleo" //Should be kept if you are using same device thing name.
+#define AWS_IOT_MQTT_TOPIC_TEST		   "Nucleo/test"
+#define AWS_IOT_MQTT_TOPIC_DATA		   "Nucleo/data"
+#define AWS_IOT_MQTT_TOPIC_SHADOW	   "$aws/things/Nucleo/shadow/update"
+#define AWS_IOT_ID ""
+#define AWS_IOT_AUTH_TOKEN ""
+
+// WiFi network credential
+#define SSID   ""  // Network must be visible otherwise it can't connect
+#define PASSW  ""
+#error "Wifi SSID & password empty"
+
+#include "stdint.h"
+
+
+/**********************************************************************************************
+***********************************************************************************************
+													Root CA certificate: Never modify
+***********************************************************************************************
+***********************************************************************************************/
+
+//This root CA can be used.
+const uint8_t rootCA[] = "\
+-----BEGIN CERTIFICATE-----\n\
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp\
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW\
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0\
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL\
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW\
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln\
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp\
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y\
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1\
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex\
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz\
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG\
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+\
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/\
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E\
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH\
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy\
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv\
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE\
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y\
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK\
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ\
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N\
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao8WNq\n\
+-----END CERTIFICATE-----\n";
+
+/**********************************************************************************************
+***********************************************************************************************
+													Device Identity Certificates: Modify for your AWS IoT Thing
+***********************************************************************************************
+***********************************************************************************************/
+
+/****************************************
+(somecode)-certificate.pem.crt - Amazon signed PEM sertificate.
+*****************************************/
+
+//This Client cert is example. Use own instead.
+const uint8_t clientCRT[] = "\
+-----BEGIN CERTIFICATE-----\n\
+MIIDBjCCAe6gAwIBAgIUVph856omeIxW3UPioq+UrX1DbwowDQYJKoZIhvcNAQEL\
+BQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\
+SW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTE3MDUyNTExNTEy\
+OVoXDEQ5MTIzMEIzNTk1OVowgZUxCzAJBgNVBAETAkJZMQ4wDAYDVQQIDAVNaW5z\
+azEOMAwGA1UEBwwFTWluc2sxFzAVBgNVBAoMDktsaWthLVRlY2ggTExDMRcwFQYD\
+VQQLDA5LbGlrYS1UZWNoIExMQzEMMAoGA1UEAwwDUm5EMSYwJAYJKoZIhvcNAQkB\
+FhdtdmF0YExldUBrbGlrYS10ZWNoLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH\
+A0IABCJgOQJmoTBJVPfEi9Hm/JVixaxkY5rtlgrYO3hSl633A2hg0P/ue0wXDbF3\
+aQ0X57IRFE4k4FEbr3UXjT/IczKjYDBeMB8GA1UdIwQYMBaAFK3YzTUPlYB2Li75\
+i/z8rEogr1d6MB0GA1UdDgQWBBT18HXBaXFJuER/0SwegnxJ+pyJ6TAMBgNVHRMB\
+Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAb0Ux1aH5\
+RLxjrfGqXN6rPVqh8QQRS+AyBfzmaQN8HaPZMkX5WxXLvcn0A3uWlwQxPPkcZ4zf\
+51GHtFFQWB4YZ8dx8mUQ0v/j7onHjCJgZ8iDgwOyKMGtnsDEWCakQw+a6cj+NrMZ\
+tzhjwCzEEP6EPcbXwErI5OOzLuWns2L/JEr2wWNkokgRuS8ewr/SQ9OLWIWa2rFM\
+ahPNTb3y/qBeWdjeJmhI+TOxdqIpsF8roWP25zwo/zkzCHCjXFBrL+0CA4MpxIl9\
+x02i7aAhlJ6ys80lDxdeWeeQJXRKkGknP8mcmKn3iEqqJ5s1dQePj2b5d3ldatya\
+wsxQBqqZXzIWEw==\
+\n\
+-----END CERTIFICATE-----\n";
+
+
+
+/**********************************************************************************************
+***********************************************************************************************
+													Private Key: Modify for your AWS IoT Thing
+***********************************************************************************************
+***********************************************************************************************/
+
+/********************************************************************8****************************************
+nucleo.key.pem - client key generated according to readme.
+**************************************************************************************************************/
+
+//This Client Key is example. Use own instead.
+const uint8_t clientKey[] ="\
+-----BEGIN EC PARAMETERS-----\n\
+BggqhEEOPQMBEw==\
+-----END EC PARAMETERS-----\n\
+-----BEGIN EC PRIVATE KEY-----\n\
+MHcCAQEEIHPRfWSC8/k/BsqDWKuP15dXsI9fGwpkTIsLZe6mIrAEoAoGCCqGSM49\
+AwEHoUQDQEAEImAEAEahMElU9+WL0eb8lWLFrGRjmu2WCtg7eFKXrfcDaGDQ/+57\
+TBcNsXdpDRfnshEETiTgURuvdReNP8hEMg==\
+-----END EC PRIVATE KEY-----\n";
+
+int connack_rc = 0; // MQTT connack return code
+int connectTimeout = 1000;
+int retryAttempt = 0;
+
+PressureSensor *pressure_sensor;
+HumiditySensor *humidity_sensor;
+TempSensor *temp_sensor1;
+MagneticSensor *magnetic_sensor;
+GyroSensor     *gyro_sensor;
+MotionSensor   *accel_sensor;
+
+MQTT::Message message;
+MQTTString TopicName= { AWS_IOT_MQTT_TOPIC_TEST };
+MQTT::MessageData MsgData(TopicName, message);
+
+void subscribe_cb(MQTT::MessageData & msgMQTT) {
+    char msg[MQTT_MAX_PAYLOAD_SIZE];
+    msg[0]='\0';
+    strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
+    printf ("--->>> subscribe_cb msg: %s\n\r", msg);
+}
+
+int subscribe(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
+{
+    char* pubTopic = AWS_IOT_MQTT_TOPIC_TEST;
+    return client->subscribe(pubTopic, MQTT::QOS0, subscribe_cb);
+}
+
+int connect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
+{ 
+	SpwfSAInterface& WiFi = ipstack->getWiFi();
+
+	// Network debug statements
+	LOG("=====================================\n\r");
+	LOG("Connecting WiFi.\n\r");
+	LOG("Nucleo IP ADDRESS: %s\n\r", WiFi.get_ip_address());
+	LOG("Nucleo MAC ADDRESS: %s\n\r", WiFi.get_mac_address());
+	LOG("Server Hostname: %s port: %d\n\r", AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT);
+	LOG("Client ID: %s\n\r", AWS_IOT_MQTT_CLIENT_ID);
+	//LOG("Topic: %s\n\r", AWS_IOT_MQTT_TOPIC_TEST);
+	//LOG("Subscription URL: %s\n\r", subscription_url);
+	LOG("=====================================\n\r");
+    
+    ipstack->open(&ipstack->getWiFi());
+
+    int rc=ipstack->getNTPtime();
+
+    if (rc != 0)
+	{
+    	ERROR("Get NTP time error: %d\n", rc);
+		return rc;
+	}
+
+    rc = WiFi.setSocketClientSecurity((uint8_t *)"m", (uint8_t *)rootCA, (uint8_t *)clientCRT, (uint8_t *)clientKey, (uint8_t *)AWS_IOT_MQTT_HOST, ipstack->getTime());
+
+    if (rc != 0)
+	{
+		ERROR("Set security params error: %d\n", rc);
+		return rc;
+	}
+
+    rc = ipstack->connect(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, connectTimeout);
+
+    if (rc != 0)
+    {
+    	WARN("IP Stack connect returned: %d\n", rc);
+        return rc;
+    }
+
+    printf ("--->TCP Connected\n\r");
+
+    // MQTT Connect
+    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
+    data.MQTTVersion = 4;
+    data.struct_version=0;
+    data.clientID.cstring = AWS_IOT_MQTT_CLIENT_ID;
+    //data.username.cstring = "use-token-auth";
+    //data.password.cstring = AWS_IOT_AUTH_TOKEN;
+
+    if ((rc = client->connect(data)) == 0) 
+    {
+        printf ("--->MQTT Connected\n\r");
+
+        if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",AWS_IOT_MQTT_TOPIC_TEST);
+    }
+    else
+    {
+        WARN("MQTT connect returned %d\n", rc);        
+    }
+    if (rc >= 0)
+        connack_rc = rc;
+    return rc;
+}
+
+int getConnTimeout(int attemptNumber)
+{  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
+   // after 20 attempts, retry every 10 minutes
+    return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
+}
+
+void attemptConnect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
+{
+    while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED) 
+    {    
+        if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
+        {
+            printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);        
+            return; // don't reattempt to connect if credentials are wrong
+        } 
+
+        int timeout = getConnTimeout(++retryAttempt);
+        WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
+        
+        // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
+        //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)        
+        // this works - reset the system when the retry count gets to a threshold
+        if (retryAttempt == 5)
+        {
+        	ipstack->getWiFi().reset_chip();
+            NVIC_SystemReset();
+        }
+        else
+            wait(timeout);
+    }
+}
+
+int publish(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
+{
+    MQTT::Message message;
+    char* pubTopic = AWS_IOT_MQTT_TOPIC_SHADOW;
+            
+    char buf[MQTT_MAX_PAYLOAD_SIZE];
+    float temp, press, hum;
+    int32_t magnet[3];
+    int32_t gyro[3];
+    int32_t accel[3];
+
+    temp_sensor1->GetTemperature(&temp);
+    pressure_sensor->GetPressure(&press);
+    humidity_sensor->GetHumidity(&hum);
+    magnetic_sensor->Get_M_Axes(magnet);
+    gyro_sensor->Get_G_Axes(gyro);
+    accel_sensor->Get_X_Axes(accel);
+
+    /*sprintf(buf,
+     "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
+              temp, press, hum);*/
+
+    if (!myButtonPressed)
+    {
+    	butled = 1;
+    	sprintf(buf, "{\"state\": {\"reported\": {\"temperature\": %f, \"humidity\": %f, \"pressure\": %f, \"accelerometer\": [%f, %f, %f], \"gyroscope\": [%f, %f, %f], \"magnetometer\": [%f, %f, %f]}}}",
+    			temp, hum, press, accel[0]/1000.0, accel[1]/1000.0, accel[2]/1000.0, gyro[0]/1000.0, gyro[1]/1000.0, gyro[2]/1000.0, magnet[0]/10.0, magnet[1]/10.0, magnet[2]/10.0);
+    }
+    else
+    {
+    	myButtonPressed = false; // reset state
+    	butled = 0;
+
+    	sprintf(buf, "{\"temperature\": %f, \"humidity\": %f, \"pressure\": %f, \"accelerometer\": [%f, %f, %f], \"gyroscope\": [%f, %f, %f], \"magnetometer\": [%f, %f, %f], \"marker\": true}",
+    	    			temp, hum, press, accel[0]/1000.0, accel[1]/1000.0, accel[2]/1000.0, gyro[0]/1000.0, gyro[1]/1000.0, gyro[2]/1000.0, magnet[0]/10.0, magnet[1]/10.0, magnet[2]/10.0);
+    	pubTopic = AWS_IOT_MQTT_TOPIC_DATA;
+    }
+
+    message.qos = MQTT::QOS0;
+    message.retained = false;
+    message.dup = false;
+    message.payload = (void*)buf;
+    message.payloadlen = strlen(buf);
+    
+    printf("Length - %d, Publishing %s\n\r", strlen(buf), buf);
+
+    return client->publish(pubTopic, message);
+} 
+
+void pressed()
+{
+	myButtonPressed = true;
+}
+
+int main()
+{
+    const char * ssid = SSID; // Network must be visible otherwise it can't connect
+    const char * seckey = PASSW;
+
+    pc.baud(115200);
+
+    SpwfSAInterface spwf(D8, D2, false);
+    
+    myled=0;
+    DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL);
+    i2c->frequency(400000);    
+    
+    mybutton.fall(&pressed);
+
+    X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(i2c);   
+    pressure_sensor = mems_expansion_board->pt_sensor;
+    temp_sensor1 =    mems_expansion_board->ht_sensor;
+    humidity_sensor = mems_expansion_board->ht_sensor;
+    magnetic_sensor = mems_expansion_board->magnetometer;
+    gyro_sensor     = mems_expansion_board->GetGyroscope();
+    accel_sensor    = mems_expansion_board->GetAccelerometer();
+    
+    pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n");     
+    pc.printf("\r\nconnecting to AP\r\n");            
+
+	MQTTWiFi ipstack(spwf, ssid, seckey, NSAPI_SECURITY_WPA2);
+
+	LOG("Connected to WiFI.\r\n");
+
+	MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
+
+	attemptConnect(&client, &ipstack);
+
+	if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
+	{
+	  while (true)
+	  wait(1.0); // Permanent failures - don't retry
+	}
+
+	myled=1;
+
+	int count = 0;
+
+	while (true)
+	{
+		if (++count == 100)
+		{
+			myled = 0;
+			// Publish a message every second
+			if (publish(&client, &ipstack) != 0)
+			{
+				myled=0;
+				ipstack.getWiFi().reset_chip();
+				NVIC_SystemReset();
+				attemptConnect(&client, &ipstack);   // if we have lost the connection
+			}
+			else myled=1;
+
+			count = 0;
+		}
+
+		client.yield(10);  // allow the MQTT client to receive messages
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Sep 27 14:40:52 2017 +0300
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/2e9cc70d1897
\ No newline at end of file