Add event feature.
authorJoseph Morrow <joseph.l.morrow@intel.com>
Wed, 30 Sep 2015 19:54:44 +0000 (12:54 -0700)
committerJon A. Cruz <jonc@osg.samsung.com>
Fri, 2 Oct 2015 20:38:41 +0000 (20:38 +0000)
Change-Id: Iafae4e422c43bc37e4304f0a00d980b38a13aa99
Signed-off-by: Thuyen Tran <thuyen.c.tran@intel.com>
Signed-off-by: Joseph Morrow <joseph.l.morrow@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2953
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
plugins/zigbee_wrapper/src/zigbee_wrapper.c
plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_socket.h
plugins/zigbee_wrapper/telegesis_wrapper/include/telegesis_wrapper.h
plugins/zigbee_wrapper/telegesis_wrapper/include/twtypes.h
plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_socket.c
plugins/zigbee_wrapper/telegesis_wrapper/src/telegesis_wrapper.c

index 7af6390..0b242d1 100644 (file)
@@ -292,8 +292,7 @@ OCStackResult ZigbeeStop(PIPlugin_Zigbee * plugin)
 OCStackResult ZigbeeProcess(PIPlugin_Zigbee * plugin)
 {
     (void)plugin;
-    // Invoke TelegesisProcess() at some point.
-    return OC_STACK_OK;
+    return TWProcess();
 }
 
 // Function returns an OIC Smart Home resource Type
index 23cde1d..4ef6489 100644 (file)
@@ -59,6 +59,8 @@ typedef enum
     TW_SEQ,
     TW_ZENROLLREQ,
     TW_ENROLLED,
+    TW_ZONESTATUS,
+    TW_ADDRESS_RESPONSE,
     TW_NONE,
     TW_MAX_ENTRY
 } TWEntryType;
index 28d6825..eea7128 100644 (file)
@@ -132,6 +132,7 @@ typedef struct
 typedef void (*TWDeviceFoundCallback)(TWDevice* device);
 typedef void (*TWEnrollmentSucceedCallback)(TWEnrollee* enrollee);
 typedef void (*TWDeviceStatusUpdateCallback)(TWUpdate* update);
+typedef void (*TWInitCompleteCallback)(bool status);
 
 /**
  *
@@ -208,7 +209,7 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState);
  *
  * @param[in] level The The meaning of ‘level’ is device dependent
  *                  e.g. for a light it may mean brightness level.
-
+ *
  * @param[in] transTime The time taken to move to the new level
  *
  */
@@ -228,12 +229,24 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta
 
 /**
  *
+ * Move Color Temperature
+ *
+ * @param[in] nodeId The node id of the device.
+ * @param[in] endpointId The endpoint id from which the attribute belongs.
+ * @param[in] colorTemperature 16 bit hexadecimal number.
+ * @param[in] transTime The time taken to move to the new level.
+ *
+ */
+OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId,
+                                            char* colorTemperature, char* transTime);
+
+/**
+ *
  * Sets discovery callback.
  * This callback will be called when TWDiscover() discovers ZigBee device(s).
  *
  */
 OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback);
-
 /**
  *
  * Sets status update callback.
@@ -255,6 +268,13 @@ OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId);
 
 /**
  *
+ * Process TWEntry.
+ *
+ */
+OCStackResult TWProcess();
+
+/**
+ *
  * Uninitializes the Telegesis module.
  *
  */
index 6b98a64..373bed7 100644 (file)
@@ -50,27 +50,35 @@ extern "C" {
 
 #define SIMPLEDESC_RESPONSE_EXPECTED_LINES (6)
 
-#define AT_STR_ERROR_OK         "00"
+#define AT_STR_ERROR_OK             "00"
+#define AT_STR_ERROR_INVALID_OP     "70"
+
+#define AT_STR_ERROR_EVERYTHING_OK                              "00"
+#define AT_STR_ERROR_NODE_IS_PART_OF_PAN                        "28"
+#define AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY    "66"
+#define AT_STR_ERROR_INVALID_OPERATION                          "70"
+
 
 #define SENDMODE                "0"
 #define SEPARATOR               ","
 #define SEPARATOR_LENGTH        strlen(SEPARATOR)
 
-#define AT_CMD_RESET                "AT&F"
-#define AT_CMD_GET_NETWORK_INFO     "AT+N"
-#define AT_CMD_ESTABLISH_NETWORK    "AT+EN"
-#define AT_CMD_PERMIT_JOIN          "AT+PJOIN:"
-#define AT_CMD_MATCH_REQUEST        "AT+MATCHREQ:"
-#define AT_CMD_SIMPLE_DESC          "AT+SIMPLEDESC:"
-#define AT_CMD_WRITE_ATR            "AT+WRITEATR:"
-#define AT_CMD_READ_ATR             "AT+READATR:"
-#define AT_CMD_RUN_ON_OFF           "AT+RONOFF:"
-#define AT_CMD_MOVE_TO_LEVEL        "AT+LCMVTOLEV:"
-#define AT_CMD_DOOR_LOCK            "AT+DRLOCK:"
-#define AT_CMD_GET_LOCAL_EUI        "ATS04?"
-#define AT_CMD_REMOTE_EUI_REQUEST   "AT+EUIREQ:"
-
-#define TW_ENDCONTROL_ERROR_STRING  "ERROR:"
+#define AT_CMD_RESET                                    "AT&F"
+#define AT_CMD_GET_NETWORK_INFO                         "AT+N"
+#define AT_CMD_ESTABLISH_NETWORK                        "AT+EN"
+#define AT_CMD_PERMIT_JOIN                              "AT+PJOIN:"
+#define AT_CMD_MATCH_REQUEST                            "AT+MATCHREQ:"
+#define AT_CMD_SIMPLE_DESC                              "AT+SIMPLEDESC:"
+#define AT_CMD_WRITE_ATR                                "AT+WRITEATR:"
+#define AT_CMD_READ_ATR                                 "AT+READATR:"
+#define AT_CMD_RUN_ON_OFF                               "AT+RONOFF:"
+#define AT_CMD_MOVE_TO_LEVEL                            "AT+LCMVTOLEV:"
+#define AT_CMD_DOOR_LOCK                                "AT+DRLOCK:"
+#define AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE     "AT+CCMVTOCT:"
+#define AT_CMD_GET_LOCAL_EUI                            "ATS04?"
+#define AT_CMD_REMOTE_EUI_REQUEST                       "AT+EUIREQ:"
+
+#define TW_ENDCONTROL_ERROR_STRING                      "ERROR:"
 
 #define SIZE_EUI                    (17)
 #define SIZE_NODEID                 (5)
@@ -122,6 +130,7 @@ typedef enum
     TW_RESULT_ERROR_INVALID_PARAMS,
     TW_RESULT_ERROR_INVALID_PORT,
     TW_RESULT_ERROR_NO_MEMORY,
+    TW_RESULT_ERROR_INVALID_OP,
     TW_RESULT_ERROR_NOTIMPL,
 
     TW_RESULT_ERROR = 255
index e7cc356..d4c592d 100644 (file)
@@ -88,6 +88,8 @@ static TWEntryTypePair TWEntryTypePairArray[] =
     {"SEQ:",            1, TW_SEQ},
     {"ZENROLLREQ:",     1, TW_ZENROLLREQ},
     {"ENROLLED:",       1, TW_ENROLLED},
+    {"ZONESTATUS:",     1, TW_ZONESTATUS},
+    {"AddrResp:",       1, TW_ADDRESS_RESPONSE},
     {"Unknown:",        0, TW_NONE},
     {"Unknown:",        1, TW_MAX_ENTRY}
 };
index 2a45992..6a55aeb 100644 (file)
 #include "oic_malloc.h"
 #include "logger.h"
 
-#include "telegesis_wrapper.h"
 #include "twtypes.h"
+#include "telegesis_socket.h"
+#include "telegesis_wrapper.h"
+
 
 #define TAG PCF("telegesiswrapper")     // Module Name
-#define ARRAY_LENGTH            (100)
+
+#define ARRAY_LENGTH    100
+
+#define RESPONSE_PARAMS_COUNT_NETWORK_INFO_1                (1)
+#define RESPONSE_PARAMS_COUNT_NETWORK_INFO_5                (5)
+#define RESPONSE_PARAMS_COUNT_JPAN                          (3)
+#define RESPONSE_PARAMS_COUNT_DEVICE_JOINED                 (2)
+#define RESPONSE_PARAMS_COUNT_MATCH_DESC                    (3)
+#define RESPONSE_PARAMS_COUNT_SIMPLE_DESC                   (2)
+#define RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN    (1)
+#define RESPONSE_PARAMS_COUNT_WRITE_ATTR_4                  (4)
+#define RESPONSE_PARAMS_COUNT_WRITE_ATTR_5                  (5)
+#define RESPONSE_PARAMS_COUNT_TEMPERATURE                   (5)
+#define RESPONSE_PARAMS_COUNT_RESPATTR                      (6)
+#define RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE              (3)
+#define RESPONSE_PARAMS_COUNT_DFTREP                        (5)
+#define RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP               (3)
+#define RESPONSE_PARAMS_COUNT_ZENROLLREQ                    (4)
+#define RESPONSE_PARAMS_COUNT_ENROLLED                      (3)
+#define RESPONSE_PARAMS_COUNT_ZONESTATUS_4                  (4)
+#define RESPONSE_PARAMS_COUNT_ZONESTATUS_6                  (6)
 
 //-----------------------------------------------------------------------------
 // Private internal function prototypes
 //-----------------------------------------------------------------------------
 
-static TWResultCode IssueATCommand(const char* command, uint8_t timeout,
-                                   uint64_t* atErrorCode,
-                                   char* responseArray[], char* promptArray[],
-                                   uint8_t* responseCount, uint8_t* promptCount);
-
-static TWResultCode HandleATResponse(char* responseArray[], int count);
+static TWResultCode HandleATResponse(TWEntry* entry);
+
+static TWResultCode processEntry(TWEntry* entry);
+static TWResultCode processEntryNETWORK_INFO(TWEntry* entry);
+static TWResultCode processEntryJPAN(TWEntry* entry);
+static TWResultCode processEntryEndDevice(TWEntry* entry);
+static TWResultCode processEntryMatchDesc(TWEntry* entry);
+static TWResultCode processEntrySimpleDesc(TWEntry* entry);
+static TWResultCode processEntryWriteAttr(TWEntry* entry);
+static TWResultCode processEntryReadAttr(TWEntry* entry);
+static TWResultCode processEntryTemperature(TWEntry* entry);
+static TWResultCode processEntrySwitchDoorLockState(TWEntry* entry);
+static TWResultCode processEntryZCLDefaultResponse(TWEntry* entry);
+static TWResultCode processEntryZoneEnrollRequest(TWEntry* entry);
+static TWResultCode processEntryEnrolled(TWEntry* entry);
+static TWResultCode processEntryZoneStatus(TWEntry* entry);
+static TWResultCode processEntryAddressResponse(TWEntry* entry);
 
 static TWResultCode Reset();
-static TWResultCode GetLocalEUI();
+static TWResultCode GetRemoteEUI();
 static TWResultCode CreatePAN();
-static TWResultCode EnableJoin(bool isKeyEncrypted, uint8_t* outDeviceJoinedCount);
-static TWResultCode FindMatchNodes(uint8_t* outDeviceMatchedCount);
+static TWResultCode EnableJoin(bool isKeyEncrypted);
+static TWResultCode FindMatchNodes();
 static TWResultCode FindClusters(char nodeId[], char endpoint[]);
+
 static TWResultCode TelNetworkInfoHandler(int count, char* tokens[]);
 static TWResultCode TelJpanHandler(int count, char* tokens[]);
 static TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[]);
@@ -73,29 +107,10 @@ static TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[]);
 static TWResultCode TelEnrolledHandler(int count, char* tokens[]);
 static TWResultCode TelZoneStatusHandler(int count, char* tokens[]);
 
-static TWResultCode OpenPort(int * fd);
-static TWResultCode ClosePort(int fd);
-
-static TWResultCode WriteBuffer(const char * command);
-static TWResultCode ReadBuffer(uint64_t * atErrorCode,
-                               char * responseArray[],
-                               uint8_t * count,
-                               const char * command,
-                               uint8_t timeout);
-
 static TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value);
 static int AsciiToHex(char c);
 static int Tokenize(const char *input, const char* delimiters, char* output[]);
 
-static int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock);
-
-static void CleanArray(char* responseArray[], char* promptArray[],
-                       uint8_t responseCount, uint8_t promptCount);
-static void PrintArray(char* responseArray[], char* promptArray[],
-                       uint8_t responseCount, uint8_t promptCount);
-
-static void PrintTWDevice(TWDevice* device);
-static void PrintTWDeviceList(TWDeviceList* list);
 static void DeallocateTWDeviceList();
 
 //-----------------------------------------------------------------------------
@@ -126,17 +141,9 @@ static TWATResultHandlerPair g_TWATResultHandlerPairArray[] =
     {"Unknown:",    TelNetworkInfoHandler}
 };
 
-static TWEndControlMap g_TWEndMessageMap[] =
-{
-    {"OK",      TW_ENDCONTROL_OK},
-    {"ERROR:",  TW_ENDCONTROL_ERROR},
-    {"ACK:",    TW_ENDCONTROL_ACK},
-    {"SEQ:",    TW_ENDCONTROL_SEQ}
-};
-
 //TODO: Take care of all global variables
+static PIPlugin* g_plugin = (PIPlugin*)1;
 static const char* g_port = NULL;
-static int g_fd = 0;
 
 static char g_LocalEUI[SIZE_EUI] = "";
 static char g_WIPRemoteEUI[SIZE_EUI] = "";
@@ -157,160 +164,92 @@ static TWDeviceStatusUpdateCallback g_DeviceStatusUpdateCallback = NULL;
 /*****************************************************************************/
 OCStackResult TWInitialize(const char* deviceDevPath)
 {
-    OC_LOG_V(INFO, TAG, "Enter TWInitializeZigBee().");
+    OC_LOG_V(INFO, TAG, "Enter TWInitialize()");
 
-    OCStackResult ret = OC_STACK_ERROR;
     TWResultCode twCode = TW_RESULT_ERROR;
 
     g_port = deviceDevPath;
-
     OC_LOG_V(INFO, TAG, "Attempt to open %s", deviceDevPath);
-    twCode = OpenPort(&g_fd);
+
+    twCode = TWStartSock(g_plugin, deviceDevPath);  //TODO:
 
     if (twCode != TW_RESULT_OK)
     {
-        OC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, ret);
-        ret = OC_STACK_ERROR;
+        OC_LOG_V(ERROR, TAG, "Failed to open %s because of error: %d", deviceDevPath, twCode);
+        return OC_STACK_ERROR;
     }
-    else
-    {
-        twCode = TW_RESULT_ERROR;
-
-        bool continueInit = true;
-        bool wantReset = false;
-
-        if (wantReset)
-        {
-            twCode = Reset();
-            if (twCode == TW_RESULT_OK)
-            {
-                OC_LOG_V(INFO, TAG, "ZigBee Initialization - Reset - OK.");
-                continueInit = true;
-            }
-            else
-            {
-                OC_LOG_V(INFO, TAG, "ZigBee Initialization - Reset - FAILED.");
-                continueInit = false;
-            }
-        }
 
-        if (continueInit)
-        {
-            twCode = CreatePAN();
-            if (twCode == TW_RESULT_OK)
-            {
-                OC_LOG_V(INFO, TAG, "CreatePan OK.");
+    char* eui = NULL;
+    twCode = TWGetEUI(g_plugin, &eui);
+    if (twCode != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to get EUI because of error: %d", twCode);
+        return OC_STACK_ERROR;
+    }
+    OICStrcpy(g_LocalEUI, SIZE_EUI, eui);
+    OC_LOG_V(INFO, TAG, "LocalEUI=%s", g_LocalEUI);
+    OICFree(eui);
 
-                twCode = GetLocalEUI();
-                if (twCode == TW_RESULT_OK)
-                {
-                    OC_LOG_V(INFO, TAG, "GetLocalEUI OK.");
-                    OC_LOG_V(INFO, TAG, "ZigBee Initialization - DONE.");
-                    g_ZigBeeStatus.state = ZB_STATE_INIT;
-                    ret = OC_STACK_OK;
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "GetLocalEUI FAILED.");
-                    OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW.");
-                             g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
-                     ret = OC_STACK_ERROR;
-                }
-            }
-            else
-            {
-                OC_LOG_V(ERROR, TAG, "CreatePan FAILED. Result: %d", twCode);
-                OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW.");
-                g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
-                ret = OC_STACK_ERROR;
-            }
-        }
-        else
+    bool wantReset = false;     //TODO:
+    if (wantReset)
+    {
+        twCode = Reset();
+        if (twCode != TW_RESULT_OK)
         {
-            OC_LOG_V(ERROR, TAG, "ZigBee Initialization - FAILED - MUST STOP NOW.");
-            ret = OC_STACK_ERROR;
+            OC_LOG_V(ERROR, TAG, "ZigBee Initialization - Reset");
+            return OC_STACK_ERROR;
         }
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWInitializeZigBee().");
-    return ret;
+    twCode = CreatePAN();
+    if (twCode != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "CreatePan Failed");
+        OC_LOG_V(ERROR, TAG, "TWInitialize() - MUST STOP NOW");
+        g_ZigBeeStatus.state = ZB_STATE_UNKNOWN;
+        return OC_STACK_ERROR;
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "CreatePan Succeed");
+        OC_LOG_V(INFO, TAG, "TWInitialize() Succeed");
+        return OC_STACK_OK;
+    }
 }
 
 OCStackResult TWDiscover()
 {
-    OC_LOG_V(INFO, TAG, "Enter TWDiscover().");
+    OC_LOG_V(INFO, TAG, "Enter TWDiscover()");
 
     OCStackResult ret = OC_STACK_ERROR;
     TWResultCode twRet = TW_RESULT_ERROR;
-    uint8_t deviceJoinedCount = 0;
 
     if (g_DeviceFoundCallback == NULL)
     {
-        OC_LOG_V(ERROR, TAG, "Required TWDeviceFoundCallback.");
-        ret = OC_STACK_ERROR;
+        OC_LOG_V(INFO, TAG, "Required TWDeviceFoundCallback.");
+        return OC_STACK_ERROR;
     }
-    else
-    {
-        twRet = EnableJoin(false, &deviceJoinedCount);
-
-        if (twRet == TW_RESULT_OK)
-        {
-            OC_LOG_V(INFO, TAG, "Number of devices joined:%d.", deviceJoinedCount);
-            uint8_t nodeMatchedCount = 0;
-            twRet = FindMatchNodes(&nodeMatchedCount);
-            if (twRet == TW_RESULT_FOUND_NO_MATCHED_DEVICE)
-            {
-                ret = OC_STACK_OK;
-            }
-            else if (twRet == TW_RESULT_FOUND_MATCHED_DEVICES)
-            {
-                ret = OC_STACK_OK;
-                int i = 0;
-                for (; i < g_FoundMatchedDeviceList->count; i++)
-                {
-                    g_WIPDevice = &g_FoundMatchedDeviceList->deviceList[i];
-                    twRet = FindClusters(g_WIPDevice->nodeId,
-                            g_WIPDevice->endpointOfInterest->endpointId);
-
-                    if (twRet == TW_RESULT_HAS_CLUSTERS)
-                    {
-                        OC_LOG_V(INFO, TAG, "Attempt to invoke a callback.");
-                        g_DeviceFoundCallback(g_WIPDevice);
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG,
-                                 "ERROR finding cluster for NodeID=%s,EUI=%s,EP=%s.",
-                                 g_WIPDevice->nodeId,
-                                 g_WIPDevice->eui,
-                                 g_WIPDevice->endpointOfInterest->endpointId);
-                        ret = OC_STACK_ERROR;
-                        break;
-                    }
-                    g_WIPDevice = NULL;
-                }
-            }
-            else
-            {
-                OC_LOG_V(ERROR, TAG, "Find matched nodes.");
-                ret = OC_STACK_ERROR;
-            }
-        }
-        else
-        {
-            OC_LOG_V(ERROR, TAG, "Enable joining.");
-            ret = OC_STACK_ERROR;
-        }
 
-        //Done with wip device.
-        g_WIPDevice = NULL;
+    twRet = EnableJoin(false);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "EnableJoin");
+        return OC_STACK_ERROR;
+    }
 
-        //deallocate the list of found devices.
-        //so that it's cleaned for the next TWDiscover() call.
-        DeallocateTWDeviceList();
+    twRet = FindMatchNodes();
+    if (twRet == TW_RESULT_OK)
+    {
+        OC_LOG_V(INFO, TAG, "FindMatchNodes");
+        ret = OC_STACK_OK;
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "FindMatchNodes");
+        ret = OC_STACK_ERROR;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWDiscover().");
+    OC_LOG_V(INFO, TAG, "Leave TWDiscover() with ret=%d", ret);
     return ret;
 }
 
@@ -320,7 +259,7 @@ OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin
 {
     //Ask:  AT+WRITEATR:5DA7,01,0,0003,0000,21,01
 
-    OC_LOG_V(INFO, TAG, "Enter TWSetAttribute().");
+    OC_LOG_V(INFO, TAG, "Enter TWSetAttribute()");
 
     (void)extendedUniqueId;
 
@@ -336,74 +275,54 @@ OCStackResult TWSetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin
                 SEPARATOR_LENGTH + strlen(newValue) + 1;
 
     char* cmdString = (char*)OICMalloc(size * sizeof(char));
-    if (cmdString != NULL)
+    if (cmdString == NULL)
     {
-        snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s",
-                 AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE,
-                 clusterId, attributeId, attributeType, newValue);
-
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
-
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    snprintf(cmdString, size, "%s%s,%s,%s,%s,%s,%s,%s",
+             AT_CMD_WRITE_ATR, nodeId, endpointId, SENDMODE,
+             clusterId, attributeId, attributeType, newValue);
 
-        uint64_t atErrorCode = 0;
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
 
-        OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString);
-        twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS,
-                               &atErrorCode,
-                               responseArray, promptArray,
-                               &responseCount, &promptCount);
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_WRITEATTR);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(INFO, TAG, "TWEntry is NULL.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        if (twRet != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Failed to write: %s", cmdString);
-            ret = OC_STACK_ERROR;
-        }
-        else
-        {
-            if (atErrorCode != AT_ERROR_EVERYTHING_OK)
-            {
-                OC_LOG_V(ERROR, TAG,
-                         "Write to a remote attribute - AT_ERROR: %" PRId64 "", atErrorCode);
-                ret = OC_STACK_ERROR;
-            }
-            else
-            {
-                OC_LOG_V(INFO, TAG, "Issue AT Command %s returned OK.", cmdString);
-                PrintArray(responseArray, promptArray, responseCount, promptCount);
-
-                //IMPORTANT NOTE:
-                //      Although responseArray is not NULL sometimes,
-                //      do not use it to check for prompt.
-                //      WRITEATTR prompt is stored in promptArray.
-                if (promptCount > 0)
-                {
-                    twRet = HandleATResponse(promptArray, promptCount);
-                    if (twRet == TW_RESULT_OK)
-                    {
-                        OC_LOG_V(INFO, TAG, "Set attribute value received a succeed prompt.");
-                        ret = OC_STACK_OK;
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG, "Set attribute value received an error prompt.");
-                        ret = OC_STACK_ERROR;
-                    }
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "Why didn't it receive WRITEATTR prompt?");
-                    ret = OC_STACK_ERROR;
-                }
-            }
-        }
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-        OICFree(cmdString);
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWSetAttribute().");
+    ret = OC_STACK_OK;
+
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWSetAttribute() with ret=%d", ret);
     return ret;
 }
 
@@ -413,7 +332,7 @@ OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin
 {
     //Ask:  AT+READATR:FE5A,01,0,0402,0002
 
-    OC_LOG_V(INFO, TAG, "Enter TWGetAttribute().");
+    OC_LOG_V(INFO, TAG, "Enter TWGetAttribute()");
 
     (void)extendedUniqueId;
 
@@ -431,86 +350,73 @@ OCStackResult TWGetAttribute(char* extendedUniqueId, char* nodeId, char* endpoin
     {
         OC_LOG_V(ERROR, TAG, "No Memory");
         ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
-    else
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
+                             AT_CMD_READ_ATR, nodeId,
+                             SEPARATOR, endpointId,
+                             SEPARATOR, SENDMODE,
+                             SEPARATOR, clusterId,
+                             SEPARATOR, attributeId);
+    if(stringRet <= 0)
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
-                 AT_CMD_READ_ATR, nodeId,
-                 SEPARATOR, endpointId,
-                 SEPARATOR, SENDMODE,
-                 SEPARATOR, clusterId,
-                 SEPARATOR, attributeId);
-
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
-
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
-
-        uint64_t atErrorCode = 0;
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
 
-        OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString);
-        twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS,
-                               &atErrorCode,
-                               responseArray, promptArray,
-                               &responseCount, &promptCount);
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_RESPATTR);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(INFO, TAG, "TWEntry is NULL");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        if (twRet != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
-            ret = OC_STACK_ERROR;
-        }
-        else
-        {
-            if (atErrorCode != AT_ERROR_EVERYTHING_OK)
-            {
-                OC_LOG_V(ERROR, TAG,
-                         "Read a remote attribute - AT_ERROR: %" PRId64 ".", atErrorCode);
-                ret = OC_STACK_ERROR;
-            }
-            else
-            {
-                OC_LOG_V(INFO, TAG, "Issue AT Command %s returned OK.", cmdString);
-                PrintArray(responseArray, promptArray, responseCount, promptCount);
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-                if (promptCount > 0)
-                {
-                    twRet = HandleATResponse(promptArray, promptCount);
-                    if (twRet == TW_RESULT_REMOTE_ATTR_HAS_VALUE)
-                    {
-                        OC_LOG_V(INFO, TAG, "Get attribute value received a succeed prompt.");
-                        int size = strlen(g_ZigBeeStatus.remoteAttributeValueRead) + 1;
-                        *outValue = (char*)OICMalloc(sizeof(char) * size);
-                        if (*outValue != NULL)
-                        {
-                            OICStrcpy(*outValue, size, g_ZigBeeStatus.remoteAttributeValueRead);
-                            *outValueLength = g_ZigBeeStatus.remoteAtrributeValueReadLength;
-                            ret = OC_STACK_OK;
-                        }
-                        else
-                        {
-                            ret = OC_STACK_NO_MEMORY;
-                        }
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG, "Get attribute value received an error prompt.");
-                        ret = OC_STACK_ERROR;
-                    }
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "Didn't receive READATTR prompt.");
-                    ret = OC_STACK_ERROR;
-                }
-            }
-        }
-        OICFree(cmdString);
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
+    size = strlen(g_ZigBeeStatus.remoteAttributeValueRead) + 1;
+    *outValue = (char*)OICMalloc(sizeof(char) * size);
+    if (*outValue == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWGetAttribute().");
+    OICStrcpy(*outValue, size, g_ZigBeeStatus.remoteAttributeValueRead);
+    *outValueLength = g_ZigBeeStatus.remoteAtrributeValueReadLength;
+    OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
+    g_ZigBeeStatus.remoteAttributeValueRead = NULL;
+    g_ZigBeeStatus.remoteAtrributeValueReadLength = 0;
+    OC_LOG_V(INFO, TAG, "TWGetAttribute() gets an attribute value.");
+    ret = OC_STACK_OK;
 
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWGetAttribute() with ret=%d", ret);
     return ret;
 }
 
@@ -521,7 +427,7 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState)
     //      OK
     //      DFTREP:9E2B,01,0006,01,00
 
-    OC_LOG_V(INFO, TAG, "Enter TWSwitchOnOff().");
+    OC_LOG_V(INFO, TAG, "Enter TWSwitchOnOff()");
 
     OCStackResult ret = OC_STACK_ERROR;
     TWResultCode twRet = TW_RESULT_UNKNOWN;
@@ -544,69 +450,64 @@ OCStackResult TWSwitchOnOff(char* nodeId, char* endpointId, char* newState)
     char* cmdString = (char*)OICMalloc(size * sizeof(char));
     if (cmdString == NULL)
     {
+        OC_LOG_V(ERROR, TAG, "No Memory");
         ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
-    else
+
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
+                             AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR,
+                             endpointId, SEPARATOR, SENDMODE);
+    if(stringRet <= 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (newState != NULL)
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s",
-                 AT_CMD_RUN_ON_OFF, nodeId, SEPARATOR,
-                 endpointId, SEPARATOR, SENDMODE);
+        OICStrcat(cmdString, size, SEPARATOR);
+        OICStrcat(cmdString, size, newState);
+    }
 
-        if (newState != NULL)
-        {
-            OICStrcat(cmdString, size, SEPARATOR);
-            OICStrcat(cmdString, size, newState);
-        }
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
 
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        uint64_t atErrorCode = 0;
-        twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS,
-                               &atErrorCode,
-                               responseArray, promptArray,
-                               &responseCount, &promptCount);
+    ret = OC_STACK_OK;
 
-        if (twRet != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Write AT+RONOFF - FAILED.");
-            ret = OC_STACK_ERROR;
-        }
-        else
-        {
-            if (atErrorCode == AT_ERROR_EVERYTHING_OK)
-            {
-                twRet = HandleATResponse(promptArray, promptCount);
-                if (twRet == TW_RESULT_OK)
-                {
-                    ret = OC_STACK_OK;
-                }
-                else
-                {
-                    ret = OC_STACK_ERROR;
-                }
-            }
-            else
-            {
-                 if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY)
-                 {
-                     OC_LOG_V(ERROR, TAG,
-                              "Switch to ON/OFF - FAILED - Send to the target not succeed.");
-                 }
-                 else
-                 {
-                     OC_LOG_V(ERROR, TAG, "Switch to ON/OFF - FAILED.");
-                 }
-                 ret = OC_STACK_ERROR;
-            }
-        }
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-        OICFree(cmdString);
-    }
-    OC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff().");
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWSwitchOnOff() with ret=%d", ret);
     return ret;
 }
 
@@ -615,7 +516,7 @@ OCStackResult TWMoveToLevel(char* nodeId, char* endpointId,
 {
     //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
 
-    OC_LOG_V(INFO, TAG, "Enter TWMoveToLevel().");
+    OC_LOG_V(INFO, TAG, "Enter TWMoveToLevel()");
 
     OCStackResult ret = OC_STACK_ERROR;
     TWResultCode twRet = TW_RESULT_UNKNOWN;
@@ -631,69 +532,64 @@ OCStackResult TWMoveToLevel(char* nodeId, char* endpointId,
     char* cmdString = (char*)OICMalloc(size * sizeof(char));
     if (cmdString == NULL)
     {
+        OC_LOG_V(ERROR, TAG, "No Memory");
         ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
-    else
+
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s",
+                             AT_CMD_MOVE_TO_LEVEL, nodeId,
+                             SEPARATOR, endpointId,
+                             SEPARATOR, SENDMODE,
+                             SEPARATOR, onOffState,
+                             SEPARATOR, level,
+                             SEPARATOR, transTime);
+    if(stringRet <= 0)
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s",
-                 AT_CMD_MOVE_TO_LEVEL, nodeId,
-                 SEPARATOR, endpointId,
-                 SEPARATOR, SENDMODE,
-                 SEPARATOR, onOffState,
-                 SEPARATOR, level,
-                 SEPARATOR, transTime);
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
 
-        uint64_t atErrorCode = 0;
-        twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS,
-                               &atErrorCode,
-                               responseArray, promptArray,
-                               &responseCount, &promptCount);
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        if (twRet != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Write AT+RONOFF - FAILED.");
-            ret = OC_STACK_ERROR;
-        }
-        else
-        {
-            if (atErrorCode == AT_ERROR_EVERYTHING_OK)
-            {
-                twRet = HandleATResponse(promptArray, promptCount);
-                if (twRet == TW_RESULT_OK)
-                {
-                    ret = OC_STACK_OK;
-                }
-                else
-                {
-                    ret = OC_STACK_ERROR;
-                }
-            }
-            else
-            {
-                 if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY)
-                 {
-                     OC_LOG_V(ERROR, TAG,
-                              "Turn To Level - FAILED - Send to the target not succeeded.");
-                 }
-                 else
-                 {
-                     OC_LOG_V(ERROR, TAG, "Turn To Level - FAILED.");
-                 }
-                 ret = OC_STACK_ERROR;
-            }
-        }
-
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-        OICFree(cmdString);
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWMoveToLevel().");
+    ret = OC_STACK_OK;
+
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWMoveToLevel() with ret=%d", ret);
     return ret;
 }
 
@@ -701,7 +597,7 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta
 {
     //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
 
-    OC_LOG_V(INFO, TAG, "Enter TWSwitchDoorLockState().");
+    OC_LOG_V(INFO, TAG, "Enter TWSwitchDoorLockState()");
 
     OCStackResult ret = OC_STACK_ERROR;
     TWResultCode twRet = TW_RESULT_UNKNOWN;
@@ -715,73 +611,150 @@ OCStackResult TWSwitchDoorLockState(char* nodeId, char* endpointId, char* newSta
     char* cmdString = (char*)OICMalloc(size * sizeof(char));
     if (cmdString == NULL)
     {
+        OC_LOG_V(ERROR, TAG, "No Memory");
         ret = OC_STACK_NO_MEMORY;
+        goto exit;
     }
-    else
+
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s",
+                             AT_CMD_DOOR_LOCK, nodeId,
+                             SEPARATOR, endpointId,
+                             SEPARATOR, SENDMODE,
+                             SEPARATOR, newState);
+    if(stringRet <= 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s%s%s",
-                 AT_CMD_DOOR_LOCK, nodeId,
-                 SEPARATOR, endpointId,
-                 SEPARATOR, SENDMODE,
-                 SEPARATOR, newState);
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
 
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        uint64_t atErrorCode = 0;
-        twRet = IssueATCommand(cmdString, TIME_OUT_05_SECONDS,
-                               &atErrorCode,
-                               responseArray, promptArray,
-                               &responseCount, &promptCount);
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        if (twRet != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Write AT+DRLOCK - FAILED.");
-            ret = OC_STACK_ERROR;
-        }
-        else
-        {
-            if (atErrorCode == AT_ERROR_EVERYTHING_OK)
-            {
-                twRet = HandleATResponse(promptArray, promptCount);
-                if (twRet == TW_RESULT_OK)
-                {
-                    ret = OC_STACK_OK;
-                }
-                else
-                {
-                    ret = OC_STACK_ERROR;
-                }
-            }
-            else
-            {
-                if (atErrorCode == AT_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY)
-                {
-                    OC_LOG_V(ERROR, TAG,
-                             "Switch to ON/OFF - FAILED - Send to the target not succeeded.");
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "Switch to ON/OFF - FAILED.");
-                }
-                ret = OC_STACK_ERROR;
-            }
-        }
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState() with ret=%d", ret);
+    return ret;
+}
+
+OCStackResult TWColorMoveToColorTemperature(char* nodeId, char* endpointId,
+                                            char* colorTemperature, char* transTime)
+{
+
+    //AT+CCMVTOCT:<Address>,<EP>,<SendMode>,<ColorTemperature>,<TransTime>
+    //  OK
+    //  ERROR:<errorcode>
+
+    OC_LOG_V(INFO, TAG, "Enter TWColorMoveToColorTemperature()");
+
+    OCStackResult ret = OC_STACK_ERROR;
+    TWResultCode twRet = TW_RESULT_UNKNOWN;
+
+    int size = 0;
+    size =  strlen(AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE) + strlen(nodeId) +
+            SEPARATOR_LENGTH + strlen(endpointId) +
+            SEPARATOR_LENGTH + strlen(SENDMODE) +
+            SEPARATOR_LENGTH + strlen(colorTemperature) +
+            SEPARATOR_LENGTH + strlen(transTime) + 1;
+
+    char* cmdString = (char*)OICMalloc(size * sizeof(char));
+    if (cmdString == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = OC_STACK_NO_MEMORY;
+        goto exit;
+    }
+
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s",
+                             AT_CMD_COLOR_CTRL_MOVE_TO_COLOR_TEMPERATURE, nodeId,
+                             SEPARATOR, endpointId,
+                             SEPARATOR, SENDMODE,
+                             SEPARATOR, colorTemperature,
+                             SEPARATOR, transTime);
+    if(stringRet <= 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    twRet = TWIssueATCommand(g_plugin, cmdString);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
+
+    TWEntry* entry = NULL;
+    twRet = TWDequeueEntry(g_plugin, &entry, TW_DFTREP);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
 
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-        OICFree(cmdString);
+    twRet = processEntry(entry);
+    if (twRet != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+        ret = OC_STACK_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWSwitchDoorLockState().");
+    ret = OC_STACK_OK;
+
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave TWColorMoveToColorTemperature() with ret=%d", ret);
     return ret;
 }
 
 OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback)
 {
-    OC_LOG_V(INFO, TAG, "Enter TWSetDiscoveryCallback().");
+    OC_LOG_V(INFO, TAG, "Enter TWSetDiscoveryCallback()");
     if (callback != NULL)
     {
         g_DeviceFoundCallback= callback;
@@ -791,458 +764,423 @@ OCStackResult TWSetDiscoveryCallback(const TWDeviceFoundCallback callback)
         g_DeviceFoundCallback = NULL;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback().");
+    OC_LOG_V(INFO, TAG, "Leave TWSetDiscoveryCallback() with ret=%d", OC_STACK_OK);
     return OC_STACK_OK;
 }
 
-OCStackResult TWUninitialize()
+OCStackResult TWSetStatusUpdateCallback(TWDeviceStatusUpdateCallback callback)
 {
-    OC_LOG_V(INFO, TAG, "Enter TWUninitializeZigBee().");
-
-    OCStackResult ret = OC_STACK_ERROR;
-
-    TWResultCode twRet = ClosePort(g_fd);
-    if (twRet == TW_RESULT_OK)
+    OC_LOG_V(INFO, TAG, "Enter TWSetStatusUpdateCallback()");
+    if (callback != NULL)
     {
-        ret = OC_STACK_OK;
+        g_DeviceStatusUpdateCallback= callback;
     }
     else
     {
-        ret = OC_STACK_ERROR;
+        g_DeviceStatusUpdateCallback = NULL;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee().");
-    return ret;
+    OC_LOG_V(INFO, TAG, "Leave TWSetStatusUpdateCallback() with ret=%d", OC_STACK_OK);
+    return OC_STACK_OK;
 }
 
-//-----------------------------------------------------------------------------
-// Internal functions
-//-----------------------------------------------------------------------------
-
-TWResultCode Reset()
+OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId)
 {
-    OC_LOG_V(INFO, TAG, "Enter Reset().");
+    OC_LOG_V(INFO, TAG, "Enter TWListenForStatusUpdates()");
 
-    TWResultCode ret = TW_RESULT_ERROR;
+    char* zoneClusterID = "0500";
+    char* zoneAttributeID = "0010";
+    char* attributeDateType = "F0";
 
-    char* responseArray[ARRAY_LENGTH] = {};
-    uint8_t responseCount = 0;
-    char* promptArray[ARRAY_LENGTH] = {};
-    uint8_t promptCount = 0;
-    uint64_t atErrorCode = 0;
+    OCStackResult ret = TWSetAttribute(NULL, nodeId, endpointId,
+                                       zoneClusterID, zoneAttributeID, attributeDateType,
+                                       g_LocalEUI);
 
-    ret = IssueATCommand(AT_CMD_RESET, TIME_OUT_00_SECOND,
-                         &atErrorCode,
-                         responseArray, NULL,
-                         &responseCount, NULL);
+    OC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates() with ret=%d", ret);
+    return ret;
+}
 
-    if (ret != TW_RESULT_OK)
-    {
-        OC_LOG_V(ERROR, TAG, "TWriting error on AT&F.");
-        ret = TW_RESULT_ERROR;
-    }
-    else
+OCStackResult TWProcess()
+{
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    while (true)
     {
-        if (atErrorCode != AT_ERROR_EVERYTHING_OK)
+        TWEntry* entry = NULL;
+        ret = TWDequeueEntry(g_plugin, &entry, TW_NONE);
+        if (ret != TW_RESULT_OK)
         {
-            OC_LOG_V(ERROR, TAG, "Dongle Reset - FAILED - AT_ERROR: %" PRId64 "", atErrorCode);
-            ret = TW_RESULT_ERROR;
+            OC_LOG_V(ERROR, TAG, "TWDequeueEntry");
+            ret = OC_STACK_ERROR;
+            break;
         }
-        else
+        if (entry == NULL)
         {
-            OC_LOG_V(INFO, TAG, "Dongle Reset - OK.");
-            ret = TW_RESULT_OK;
+            ret = OC_STACK_OK;
+            break;
         }
 
+        ret = processEntry(entry);
+        if (ret != TW_RESULT_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "processEntry");
+            ret = TWDeleteEntry(g_plugin, entry);
+            if(ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed to delete entry.");
+                ret = OC_STACK_ERROR;
+                break;
+            }
+        }
+        else
+        {
+            OC_LOG_V(INFO, TAG, "processEntry");
+            ret = TWDeleteEntry(g_plugin, entry);
+            if(ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed to delete entry.");
+                ret = OC_STACK_ERROR;
+                break;
+            }
+        }
     }
 
-    CleanArray(responseArray, promptArray, responseCount, promptCount);
-
-    OC_LOG_V(INFO, TAG, "Leave Reset().");
     return ret;
 }
 
-TWResultCode GetLocalEUI()
+OCStackResult TWUninitialize()
 {
-    OC_LOG_V(INFO, TAG, "Enter GetLocalEUI().");
-    TWResultCode ret = TW_RESULT_UNKNOWN;
-
-    char* responseArray[ARRAY_LENGTH] = {};
-    uint8_t responseCount = 0;
-
-    char* promptArray[ARRAY_LENGTH] = {};
-    uint8_t promptCount = 0;
-
-    uint64_t atErrorCode = 0;
-
-    OC_LOG_V(INFO, TAG, "Issued Command: %s.", AT_CMD_GET_LOCAL_EUI);
-    ret = IssueATCommand(AT_CMD_GET_LOCAL_EUI, TIME_OUT_05_SECONDS,
-                         &atErrorCode,
-                         responseArray, promptArray,
-                         &responseCount, &promptCount);
+    OC_LOG_V(INFO, TAG, "Enter TWUninitializeZigBee()");
+    OCStackResult ret = OC_STACK_ERROR;
 
-    if (ret != TW_RESULT_OK)
+    TWResultCode twRet = TWStopSock(g_plugin);
+    if (twRet == TW_RESULT_OK)
     {
-        OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_LOCAL_EUI);
-        ret = TW_RESULT_ERROR;
+        OC_LOG_V(INFO, TAG, "TWStopSock");
+        ret = OC_STACK_OK;
     }
     else
     {
-        if (atErrorCode != AT_ERROR_EVERYTHING_OK)
-        {
-            OC_LOG_V(ERROR, TAG,
-                     "Get Local EUI Failed - AT_ERROR: %" PRId64 "", atErrorCode);
-            ret = TW_RESULT_ERROR;
-        }
-        else
-        {
-            OICStrcpy(g_LocalEUI, SIZE_EUI, responseArray[0]);
-            OC_LOG_V(INFO, TAG, "Local EUI: %s ", g_LocalEUI);
-            ret = TW_RESULT_OK;
-        }
+        OC_LOG_V(ERROR, TAG, "TWStopSock");
+        ret = OC_STACK_ERROR;
     }
 
-    CleanArray(responseArray, promptArray, responseCount, promptCount);
+    DeallocateTWDeviceList();
 
-    OC_LOG_V(INFO, TAG, "Leave GetLocalEUI().");
+    OC_LOG_V(INFO, TAG, "Leave TWUninitializeZigBee() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode CreatePAN()
-{
-    /*
-    //at+n
-    //      +N=NoPAN
-    //      OK
-
-    //at+n
-    //      +N=COO,26,-6,7306,133F04EA669C6B24
-    //      OK
+//-----------------------------------------------------------------------------
+// Internal functions
+//-----------------------------------------------------------------------------
 
-    //at+en
-    //      OK
-    //      JPAN:26,7306,133F04EA669C6B24
+TWResultCode processEntry(TWEntry *entry)
+{
+    OC_LOG_V(INFO, TAG, "Enter processEntry()");
 
-    //at+en
-    //      ERROR:28
-    */
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+    switch(entry->type)
+    {
+        /*
+        TW_OK,              TODO: Joey to return an TWEntry for OK
+        TW_ERROR,           TODO: Joey to return an TWEntry for ERROR
 
-    OC_LOG_V(INFO, TAG, "Enter CreatePAN()");
+        TW_INCLUSTER,
 
-    TWResultCode ret = TW_RESULT_ERROR;
+        TW_ACK,
+        TW_NACK,
+        TW_SEQ,
+        TW_MAX_ENTRY
+         */
 
-    uint8_t responseCount1 = 0;
-    uint8_t promptCount1 = 0;
-    char* responseArray1[ARRAY_LENGTH] = {};
-    char* promptArray1[ARRAY_LENGTH] = {};
+        /*
+        TODO: Joey?
+        //Ask:          AT+PJOIN
+        //Response:     OK
 
-    uint8_t responseCount2 = 0;
-    uint8_t promptCount2 = 0;
-    char* responseArray2[ARRAY_LENGTH] = {};
-    char* promptArray2[ARRAY_LENGTH] = {};
+        //Ask:          AT+PJOIN
+        //Response:     ERROR:70
 
-    uint64_t atErrorCode = 0;
+         */
 
-    ret = IssueATCommand(AT_CMD_GET_NETWORK_INFO, TIME_OUT_00_SECOND,
-                         &atErrorCode,
-                         responseArray1, promptArray1,
-                         &responseCount1, &promptCount1);
-    if (ret != TW_RESULT_OK)
-    {
-        OC_LOG_V(ERROR, TAG, "Write AT+N - FAILED.");
-        ret = TW_RESULT_ERROR;
-    }
-    else
-    {
-        if (atErrorCode != AT_ERROR_EVERYTHING_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Get network info - FAILED.");
-            ret = TW_RESULT_ERROR;
-        }
-        else
-        {
-            //Handle +N
-            ret = HandleATResponse(responseArray1, responseCount1);
-            if (ret == TW_RESULT_NO_LOCAL_PAN)
+        case TW_NETWORK_INFO:
+            ret = processEntryNETWORK_INFO(entry);
+            if ((ret != TW_RESULT_NO_LOCAL_PAN) &&
+                (ret != TW_RESULT_HAS_LOCAL_PAN))
             {
-                OC_LOG_V(INFO, TAG, "Attempt to write AT+EN. ");
-                ret = IssueATCommand(AT_CMD_ESTABLISH_NETWORK, TIME_OUT_01_SECOND,
-                                     &atErrorCode,
-                                     responseArray2, promptArray2,
-                                     &responseCount2, &promptCount2);
-
-                if (ret != TW_RESULT_OK)
-                {
-                    OC_LOG_V(ERROR, TAG, "Write AT+EN - FAILED.");
-                    ret = TW_RESULT_ERROR;
-                }
-                else
-                {
-                    if (atErrorCode == AT_ERROR_EVERYTHING_OK) //OK
-                    {
-                        //IMPORTANT: Special case for JPAN prompt:
-                        //JPAN prompts are stored in responseArray instead of promptArray
-                        //Handle JPAN:26,7306,133F04EA669C6B24
-                        ret = HandleATResponse(responseArray2, responseCount2);
-                        if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED)
-                        {
-                            OC_LOG_V(INFO, TAG, "New Local PAN established - OK.");
-                            ret = TW_RESULT_OK;
-                        }
-                        else
-                        {
-                            OC_LOG_V(ERROR, TAG, "Handling AT+EN.");
-                            ret = TW_RESULT_ERROR;
-                        }
-                    }
-                    else if (atErrorCode == AT_ERROR_NODE_IS_PART_OF_PAN)
-                    {
-                        OC_LOG_V(INFO, TAG, "Already Established PAN - OK.");
-                        ret = TW_RESULT_OK;
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG, "Couldn't establish PAN.");
-                        ret = TW_RESULT_ERROR;
-                    }
-                }
+                OC_LOG_V(ERROR, TAG, "processEntryNETWORK_INFO.");
             }
-            else if (ret == TW_RESULT_HAS_LOCAL_PAN)
+            break;
+        case TW_JPAN:
+            ret = processEntryJPAN(entry);
+            if (ret != TW_RESULT_OK)
             {
-                OC_LOG_V(INFO, TAG, "Already established PAN - OK.");
-                ret = TW_RESULT_OK;
+                OC_LOG_V(ERROR, TAG, "processEntryJPAN.");
             }
-            else if (atErrorCode != 0)
+            break;
+        case TW_SED:
+            ret = processEntryEndDevice(entry);
+            if (ret != TW_RESULT_OK)
             {
-                OC_LOG_V(ERROR, TAG,
-                         "CreatePAN() FAILED with AT_ERROR: %" PRId64 "", atErrorCode);
-                ret = TW_RESULT_ERROR;
+                OC_LOG_V(ERROR, TAG, "processEntrySED.");
             }
-        }
-    }
-
-    CleanArray(responseArray1, promptArray1, responseCount1, promptCount1);
-    CleanArray(responseArray2, promptArray2, responseCount2, promptCount2);
-
-    OC_LOG_V(INFO, TAG, "Leave CreatePAN().");
-    return ret;
-}
-
-TWResultCode EnableJoin(bool isKeyEncrypted, uint8_t* outDeviceJoinedCount)
-{
-    //Ask:          AT+PJOIN
-    //Response:     OK
+            break;
+        case TW_RFD:
+            ret = processEntryEndDevice(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryRFD.");
+            }
+            break;
+        case TW_FFD:
+            ret = processEntryEndDevice(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryFFD.");
+            }
+            break;
+        case TW_ZED:
+            ret = processEntryEndDevice(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryZED.");
+            }
+            break;
+        case TW_MATCHDESC:
+            ret = processEntryMatchDesc(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryMatchDesc.");
+            }
+            break;
+        case TW_SIMPLEDESC:
+            ret = processEntrySimpleDesc(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntrySimpleDesc.");
+            }
+            break;
+        case TW_WRITEATTR:
+            ret = processEntryWriteAttr(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryWriteAttr.");
+            }
+            break;
+        case TW_RESPATTR:
+            ret = processEntryReadAttr(entry);
+            if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryReadAttr.");
+            }
+            break;
+        case TW_TEMPERATURE:
+            ret = processEntryTemperature(entry);
+            if (ret != TW_RESULT_REMOTE_ATTR_HAS_VALUE)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryTemperature.");
+            }
+            break;
+        case TW_DRLOCRSP:
+            ret = processEntrySwitchDoorLockState(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState.");
+            }
+            break;
+        case TW_DRUNLOCKRSP:
+            ret = processEntrySwitchDoorLockState(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntrySwitchDoorLockState.");
+            }
+            break;
+        case TW_DFTREP:
+            ret = processEntryZCLDefaultResponse(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryZCLDefaultResponse.");
+            }
+            break;
+        case TW_ZENROLLREQ:
+            ret = processEntryZoneEnrollRequest(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryZoneEnrollRequest.");
+            }
+            break;
+        case TW_ENROLLED:
+            ret = processEntryEnrolled(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryEnrolled.");
+            }
+            break;
+        case TW_ZONESTATUS:
+            ret = processEntryZoneStatus(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryZoneStatus.");
+            }
+            break;
+        case TW_ADDRESS_RESPONSE:
+            ret = processEntryAddressResponse(entry);
+            if (ret != TW_RESULT_OK)
+            {
+                OC_LOG_V(ERROR, TAG, "processEntryAddressResponse.");
+            }
+            break;
+        default:
+            OC_LOG_V(ERROR, TAG, "processEntry() doesn't receive an valid entry.");
+            ret = TW_RESULT_ERROR;
+            break;
+    }
 
-    //Ask:          AT+PJOIN
-    //Response:     ERROR:70
+    OC_LOG_V(INFO, TAG, "Leave processEntry() with ret=%d", ret);
+    return ret;
+}
 
-    OC_LOG_V(INFO, TAG, "Enter Enabling Join().");
+TWResultCode processEntryNETWORK_INFO(TWEntry* entry)
+{
+    /*
+    //at+n
+    //      +N=NoPAN
+    //      OK
 
-    (void)isKeyEncrypted;
+    //at+n
+    //      +N=COO,26,-6,7306,133F04EA669C6B24
+    //      OK
+    */
 
-    TWResultCode ret = TW_RESULT_ERROR;
+    OC_LOG_V(INFO, TAG, "Enter processEntryNETWORK_INFO()");
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    if (outDeviceJoinedCount != NULL)
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        *outDeviceJoinedCount = 0;
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
 
-        isKeyEncrypted = false;         //TODO: for now - don't encrypt
+    ret = HandleATResponse(entry);
+
+exit:
+    OC_LOG_V(INFO, TAG, "Leave processEntryNETWORK_INFO() with ret=%d", ret);
+    return ret;
+}
 
-        char*   joinTimeHex     = "0F"; //TODO: for now - 15 seconds
-        uint8_t joinTimeDecimal = 15;   //TODO: for now - 15 seconds
+TWResultCode processEntryJPAN(TWEntry* entry)
+{
+    /*
+    //at+en
+    //      OK
+    //      JPAN:26,7306,133F04EA669C6B24
 
-        char* broadcast = "FFFC";
+    //at+en
+    //      ERROR:28
+    */
 
-        int size =  strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) +
-                    SEPARATOR_LENGTH + strlen(broadcast) + 1;
+    OC_LOG_V(INFO, TAG, "Enter processEntryJPAN()");
 
-        char* cmdString = (char*)OICMalloc(size * sizeof(char));
-        if (cmdString == NULL)
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) == 0)
+    {
+        ret = HandleATResponse(entry);
+        if (ret == TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED)
         {
-            ret = TW_RESULT_ERROR_NO_MEMORY;
+            OC_LOG_V(INFO, TAG, "New Local PAN established.");
+            ret =  TW_RESULT_OK;
         }
         else
         {
-            snprintf(cmdString, size, "%s%s%s%s",
-                     AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast);
-
-            char* responseArray[ARRAY_LENGTH] = {};
-            uint8_t responseCount = 0;
-
-            char* promptArray[ARRAY_LENGTH] = {};
-            uint8_t promptCount = 0;
-
-            uint64_t atErrorCode = 0;
-
-            OC_LOG_V(INFO, TAG, "Attempt to allow joining...");
-
-            OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString);
-            ret = IssueATCommand(cmdString, joinTimeDecimal,
-                                 &atErrorCode,
-                                 responseArray, promptArray,
-                                 &responseCount, &promptCount);
-
-            if (ret != TW_RESULT_OK)
-            {
-                OC_LOG_V(ERROR, TAG, "Write AT+PJOIN - AT_ERROR = %" PRId64 "", atErrorCode);
-                ret = TW_RESULT_ERROR;
-            }
-            else
-            {
-                if (atErrorCode == AT_ERROR_EVERYTHING_OK)
-                {
-                    OC_LOG_V(INFO, TAG, "Enable joining - OK.");
-                    OC_LOG_V(INFO, TAG,
-                             "Joining has been allowed for %d seconds. Time's up!",
-                             joinTimeDecimal);
-                    if (promptCount > 0)    // some devices joined.
-                    {
-                        OC_LOG_V(INFO, TAG, "Number of devices joined:%d.", promptCount);
-                        *outDeviceJoinedCount = promptCount;
-
-                        //Handle SED, FFD, RFD,...
-                        ret = HandleATResponse(promptArray, promptCount);
-                    }
-                    else
-                    {
-                        ret = TW_RESULT_OK;
-                    }
-                }
-                else if (atErrorCode == AT_ERROR_INVALID_OPERATION)
-                {
-                    OC_LOG_V(ERROR, TAG, "Enable joining - FAILED - because there was no PAN.");
-                    ret = TW_RESULT_ERROR;
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "Enable joining - FAILED.");
-                    ret = TW_RESULT_ERROR;
-                }
-            }
-            CleanArray(responseArray, promptArray, responseCount, promptCount);
+            ret = TW_RESULT_ERROR;
         }
     }
+    else if (strcmp(entry->atErrorCode, AT_STR_ERROR_NODE_IS_PART_OF_PAN) == 0)
+    {
+        OC_LOG_V(INFO, TAG, "Already Established PAN.");
+        ret = TW_RESULT_OK;
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
+    }
 
-    OC_LOG_V(INFO, TAG, "Leave Enabling Join()");
+    OC_LOG_V(INFO, TAG, "Leave processEntryJPAN() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode FindMatchNodes(uint8_t* outDeviceMatchedCount)
+TWResultCode processEntryEndDevice(TWEntry* entry)
 {
-    //AT+MATCHREQ:0104,03,0003,0006,0402,00
-    //      OK
-    //      MatchDesc:0B4A,00,01
-
-    //AT+MATCHREQ:0104,03,0999,0999,0999,00
-    //      OK
-
-    OC_LOG_V(INFO, TAG, "Enter FindMatchNodes().");
+    OC_LOG_V(INFO, TAG, "Enter processEntryEndDevice()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
+    ret = HandleATResponse(entry);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "HandleATResponse");
+    }
 
-    char* profileHomeAutomation = "0104";
-    char* inClusterCount = "04";
-    char* outClusterCount = "00";
+    OC_LOG_V(INFO, TAG, "Leave processEntryEndDevice() with ret=%d", ret);
+    return ret;
+}
 
-    //TODO: add more clusters
-    char* clusterIdentify = "0003";
-    char* clusterOnOff = "0006";
-    char* clusterTemperatureMeasurement = "0402";
-    char* clusterIASZone = "0500";
+TWResultCode processEntryMatchDesc(TWEntry* entry)
+{
+    //MatchDesc:0B4A,00,01
 
-    int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(profileHomeAutomation) +
-               SEPARATOR_LENGTH + strlen(inClusterCount) +
-               SEPARATOR_LENGTH + strlen(clusterIdentify) +
-               SEPARATOR_LENGTH + strlen(clusterOnOff) +
-               SEPARATOR_LENGTH + strlen(clusterTemperatureMeasurement) +
-               SEPARATOR_LENGTH + strlen(clusterIASZone) +
-               SEPARATOR_LENGTH + strlen(outClusterCount) + 1;
+    OC_LOG_V(INFO, TAG, "Enter processEntryMatchDesc()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    char* cmdString = (char*)OICMalloc(size * sizeof(char));
-    if (cmdString == NULL)
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        ret = TW_RESULT_ERROR_NO_MEMORY;
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-                 AT_CMD_MATCH_REQUEST, profileHomeAutomation,
-                 SEPARATOR, inClusterCount,
-                 SEPARATOR, clusterIdentify,
-                 SEPARATOR, clusterOnOff,
-                 SEPARATOR, clusterTemperatureMeasurement,
-                 SEPARATOR, clusterIASZone,
-                 SEPARATOR, outClusterCount);
-
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
-
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
-
-        uint64_t atErrorCode = 0;
-
-        OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString);
-        ret = IssueATCommand(cmdString, TIME_OUT_10_SECONDS,
-                             &atErrorCode,
-                             responseArray, promptArray,
-                             &responseCount, &promptCount);
-
-        if (ret != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Write %s - AT_ERROR = %" PRId64 ".", cmdString, atErrorCode);
-            ret = TW_RESULT_ERROR;
-        }
-        else
+        ret = HandleATResponse(entry);
+        if (ret == TW_RESULT_OK)
         {
-            if (atErrorCode != AT_ERROR_EVERYTHING_OK)
+            OC_LOG_V(INFO, TAG, "HandleATResponse");
+            ret = FindClusters(g_WIPDevice->nodeId,
+                               g_WIPDevice->endpointOfInterest->endpointId);
+            if (ret == TW_RESULT_OK)
             {
-                OC_LOG_V(ERROR, TAG,
-                         "AT_ERROR %" PRId64 " returned from %s", atErrorCode, cmdString);
-                ret = TW_RESULT_ERROR;
+                OC_LOG_V(INFO, TAG, "FindClusters - Found a match node");
+                if (g_DeviceFoundCallback != NULL)
+                {
+                    OC_LOG_V(INFO, TAG, "Found a match node -- invoke callback");
+                    g_DeviceFoundCallback(g_WIPDevice);
+                }
+                ret =  TW_RESULT_OK;
             }
             else
             {
-                OC_LOG_V(INFO, TAG, "Number of found matched nodes:%d.", promptCount);
-                if (promptCount > 0)
-                {
-                    //Handle all received MatchDesc:0B4A,00,01
-                    ret = HandleATResponse(promptArray, promptCount);
-                    if (ret == TW_RESULT_OK)
-                    {
-                        OC_LOG_V(INFO, TAG, "Handle matched nodes - SUCCEED.");
-                        *outDeviceMatchedCount = promptCount;
-                        ret = TW_RESULT_FOUND_MATCHED_DEVICES;
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG, "Handle matched nodes.");
-                        ret = TW_RESULT_ERROR;
-                    }
-                }
-                else
-                {
-                    ret = TW_RESULT_FOUND_NO_MATCHED_DEVICE;
-                }
+                OC_LOG_V(ERROR, TAG, "FindClusters");
+                ret = TW_RESULT_ERROR;
             }
         }
-
-        OICFree(cmdString);
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-
-        if (g_FoundMatchedDeviceList != NULL)
+        else
         {
-            OC_LOG_V(INFO, TAG, "Found these devices via match request.");
-            PrintTWDeviceList(g_FoundMatchedDeviceList);
+            OC_LOG_V(ERROR, TAG, "HandleATResponse");
+            ret = TW_RESULT_ERROR;
         }
+
+        g_WIPDevice = NULL; //reset and do not deallocate it
     }
 
-    OC_LOG_V(INFO, TAG, "Leave FindMatchNodes().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryMatchDesc() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode FindClusters(char nodeId[], char endpoint[])
+TWResultCode processEntrySimpleDesc(TWEntry* entry)
 {
+    /*
     //AT+SIMPLEDESC:3746,3746,01
     //      SEQ:97
     //      OK
@@ -1255,1415 +1193,1512 @@ TWResultCode FindClusters(char nodeId[], char endpoint[])
     //      OutCluster:0019
     //
     //      ACK:97
-
-    OC_LOG_V(INFO, TAG, "Enter FindClusters().");
+    */
+    OC_LOG_V(INFO, TAG, "Enter processEntrySimpleDesc()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) +
-               SEPARATOR_LENGTH + strlen(nodeId) +
-               SEPARATOR_LENGTH + strlen(endpoint) + 1;
-
-    char* cmdString = (char*)OICMalloc(size * sizeof(char));
-    if (cmdString == NULL)
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        ret = TW_RESULT_ERROR_NO_MEMORY;
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", (entry->atErrorCode));
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        snprintf(cmdString, size, "%s%s%s%s%s%s",
-                 AT_CMD_SIMPLE_DESC, nodeId,
-                 SEPARATOR, nodeId,
-                 SEPARATOR, endpoint);
-
-        char* responseArray[ARRAY_LENGTH] = {};
-        uint8_t responseCount = 0;
-
-        char* promptArray[ARRAY_LENGTH] = {};
-        uint8_t promptCount = 0;
-
-        uint64_t atErrorCode = 0;
-
-        OC_LOG_V(INFO, TAG, "Issued Command: %s.", cmdString);
-        ret = IssueATCommand(cmdString, TIME_OUT_07_SECONDS,
-                             &atErrorCode,
-                             responseArray, promptArray,
-                             &responseCount, &promptCount);
-
-        if (ret != TW_RESULT_OK)
+        if (entry->count == 6)   //must be 6 as it is the number of lines to expect
         {
-            OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
-            ret = TW_RESULT_ERROR;
+            ret = HandleATResponse(entry);
+            if (ret == TW_RESULT_HAS_CLUSTERS)
+            {
+                OC_LOG_V(INFO, TAG, "has clusters.");
+                ret = TW_RESULT_OK;
+            }
         }
         else
         {
-            if (atErrorCode != AT_ERROR_EVERYTHING_OK)
-            {
-                OC_LOG_V(ERROR, TAG,
-                         "AT_ERROR %" PRId64 " returned from %s", atErrorCode, cmdString);
-                ret = TW_RESULT_ERROR;
-            }
-            else
-            {
-                if (promptCount == SIMPLEDESC_RESPONSE_EXPECTED_LINES)
-                {
-                    //Handle - SimpleDesc...
-                    ret = HandleATResponse(promptArray, promptCount);
-                    if (ret == TW_RESULT_OK)
-                    {
-                        OC_LOG_V(INFO, TAG,
-                                 "Succeed handling clusters for nodeid %s.", nodeId);
-                        ret = TW_RESULT_HAS_CLUSTERS;
-                    }
-                    else
-                    {
-                        OC_LOG_V(ERROR, TAG, "Error handling clusters for nodeid %s.", nodeId);
-                        ret = TW_RESULT_ERROR;
-                    }
-                }
-                else
-                {
-                    OC_LOG_V(ERROR, TAG, "Received an invalid Simple Descriptor prompt.");
-                    PrintArray(responseArray, promptArray, responseCount, promptCount);
-                    ret = TW_RESULT_ERROR;
-                }
-            }
+            OC_LOG_V(INFO, TAG, "Received an invalid Simple Descriptor.");
+            ret = TW_RESULT_ERROR;
         }
-        CleanArray(responseArray, promptArray, responseCount, promptCount);
-        OICFree(cmdString);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave FindClusters().");
-
+    OC_LOG_V(INFO, TAG, "Leave processEntrySimpleDesc() returns with ret=%d", ret);
     return ret;
 }
 
-OCStackResult TWListenForStatusUpdates(char* nodeId, char* endpointId)
+TWResultCode processEntryWriteAttr(TWEntry* entry)
 {
-    OC_LOG_V(INFO, TAG, "Enter TWListenForStatusUpdates().");
+    //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
+    //      OK
+    //      WRITEATTR:3A3D,01,0003,,00
 
-    char* zoneClusterID = "0500";
-    char* zoneAttributeID = "0010";
-    char* attributeDateType = "F0";
+    OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()");
 
-    OCStackResult ret = TWSetAttribute(NULL, nodeId, endpointId,
-                                       zoneClusterID, zoneAttributeID, attributeDateType,
-                                       g_LocalEUI);
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    OC_LOG_V(INFO, TAG, "Leave TWListenForStatusUpdates().");
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
+    }
+    else
+    {
+        ret = HandleATResponse(entry);
+    }
 
+    OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret);
     return ret;
 }
 
-TWResultCode HandleATResponse(char* responseArray[], int count)
+TWResultCode processEntryReadAttr(TWEntry* entry)
 {
-    OC_LOG_V(INFO, TAG, "Enter HandleATResponse().");
+    OC_LOG_V(INFO, TAG, "Enter processEntryWriteAttr()");
 
-    TWResultCode ret = TW_RESULT_ERROR;
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    int32_t i = 0;
-    for (; i < count; i++)
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        uint32_t k = 0;
-        for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k)
-        {
-            if (strncmp(responseArray[i],
-                        g_TWATResultHandlerPairArray[k].resultTxt,
-                        strlen(g_TWATResultHandlerPairArray[k].resultTxt)
-                        ) == 0)
-            {
-                char* tokens[ARRAY_LENGTH] = {};
-                const char* delimiters = ",\r\n";
-                int paramCount = Tokenize(responseArray[i] +
-                                           strlen(g_TWATResultHandlerPairArray[k].resultTxt),
-                                           delimiters, tokens);
-                if (paramCount > 0)
-                {
-                    ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens);
-                }
-
-                int n = 0;
-                for (; n < paramCount; n++)
-                {
-                    OICFree(tokens[n]);
-                }
-
-                break;
-            }
-        }
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
+    }
+    else
+    {
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave HandleATResponse().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryWriteAttr() returns with ret=%d", ret);
     return ret;
 }
 
-//-----------------------------------------------------------------------------
-// Internal functions - AT Response/Prompt Handlers
-//-----------------------------------------------------------------------------
-
-TWResultCode TelAddressResponseHandler(int count, char* tokens[])
+TWResultCode processEntryTemperature(TWEntry* entry)
 {
-    //AddrResp:<errorcode>[,<NodeID>,<EUI64>]
-    //AddrResp:00,15ED,000D6F00040574B8
-
-    if(!tokens || count <= 3)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-
-    OC_LOG_V(INFO, TAG, "Enter TelAddressResponseHandler()");
+    OC_LOG_V(INFO, TAG, "Enter processEntryTemperature()");
 
-    TWResultCode ret = TW_RESULT_ERROR;
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    if (strcmp(tokens[0], AT_STR_ERROR_OK) != 0)
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        OC_LOG_V(ERROR, TAG, "AddrResp prompt contained error status.");
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        OICStrcpy(g_WIPRemoteNodeId, SIZE_NODEID, tokens[1]);
-        OICStrcpy(g_WIPRemoteEUI, SIZE_EUI, tokens[2]);
-        ret = TW_RESULT_OK;
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler()");
-
+    OC_LOG_V(INFO, TAG, "Leave processEntryTemperature() returns with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelNetworkInfoHandler(int count, char* tokens[])
+TWResultCode processEntrySwitchDoorLockState(TWEntry* entry)
 {
-    // Ask:         AT+N
-    // Response:    +N=COO,24,-6,9726,12BB200F073AB573
-    //                          or
-    //              +N=NoPAN
-    //
-    //              +N=<devicetype>,<channel>,<power>,<PANID>,<EPANID>
+    OC_LOG_V(INFO, TAG, "Enter processEntrySwitchDoorLockState()");
 
-    OC_LOG_V(INFO, TAG, "Enter TelNetworkInfoHandler()");
-    if(!tokens || count <= 4)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
     TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    int i = 0;
-    for (; i < count; ++i)
-    {
-        if (tokens[i] != NULL)
-        {
-            OC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]);
-        }
-    }
-
-    char* temp = tokens[0];
-    if (strcmp(temp, "NoPAN") == 0)
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): It is NoPan.");
-        ret = TW_RESULT_NO_LOCAL_PAN;
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): already have an established network.");
-        ret = AsciiHexToValue(tokens[3], 2, &g_ZigBeeStatus.panId);
-        if(ret != TW_RESULT_OK)
-        {
-            return ret;
-        }
-        ret = AsciiHexToValue(tokens[4], 8, &g_ZigBeeStatus.extPanId);
-        if(ret != TW_RESULT_OK)
-        {
-            return ret;
-        }
-        OC_LOG_V(INFO, TAG,
-                 "TelNetworkInfoHandler(): PanId=%" PRId64 "", g_ZigBeeStatus.panId);
-        OC_LOG_V(INFO, TAG,
-                 "TelNetworkInfoHandler(): ExtPanId=%" PRId64 "", g_ZigBeeStatus.extPanId);
-
-        OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): PanId=%s", tokens[3]);
-        OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler(): ExtPanId=%s", tokens[4]);
-
-        OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X",
-                 (unsigned int)(g_ZigBeeStatus.extPanId >> 32),
-                 (unsigned int)(g_ZigBeeStatus.extPanId & 0xFFFFFFFF));
-
-        ret = TW_RESULT_HAS_LOCAL_PAN;
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler()");
+    OC_LOG_V(INFO, TAG, "Leave processEntrySwitchDoorLockState() returns with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelJpanHandler(int count, char* tokens[])
+TWResultCode processEntryZCLDefaultResponse(TWEntry* entry)
 {
-    //Ask:        AT+EN:[<channel>],[<POWER>],[<PANID>]
-    //Response:   JPAN:<channel>,<PANID>,<EPANID>
-
-    OC_LOG_V(INFO, TAG, "Enter TelJpanHandler().");
-    if(!tokens || count <= 2)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    OC_LOG_V(INFO, TAG, "Enter processEntryZCLDefaultResponse()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    ret = AsciiHexToValue(tokens[1], 2, &g_ZigBeeStatus.panId);
-    if(ret != TW_RESULT_OK)
+    if (strcmp((entry->atErrorCode), AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        return ret;
+        if (strcmp(entry->atErrorCode, AT_STR_ERROR_MESSAGE_NOT_SENT_TO_TARGET_SUCCESSFULLY) == 0)
+        {
+            OC_LOG_V(ERROR, TAG, "Send to the target not succeed.");
+            ret = TW_RESULT_ERROR;
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR = %s", entry->atErrorCode);
+            ret = TW_RESULT_ERROR;
+        }
     }
-    ret = AsciiHexToValue(tokens[2], 8, &g_ZigBeeStatus.extPanId);
-    if(ret != TW_RESULT_OK)
+    else
     {
-        return ret;
+        ret = HandleATResponse(entry);
     }
-    OC_LOG_V(INFO, TAG, "PanId = %" PRId64 "", g_ZigBeeStatus.panId);
-    OC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "", g_ZigBeeStatus.extPanId);
-    ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED;
 
-    OC_LOG_V(INFO, TAG, "Leave TelJpanHandler().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryZCLDefaultResponse() returns with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[])
+TWResultCode processEntryZoneEnrollRequest(TWEntry* entry)
 {
-    //Ask:      AT+PJOIN
-    //
-    //Prompt:   RFD:<IEEE Address>,<NodeID>
-    //Prompt:   FFD:<IEEE Address>,<NodeID>
-    //Prompt:   SED:<IEEE Address>,<NodeID>
-    //Prompt:   ZED:<IEEE Address>,<NodeID>
-
-    OC_LOG_V(INFO, TAG, "Enter TelEndDeviceJoinHandler().");
-    if(!tokens || count <= 1)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    OC_LOG_V(INFO, TAG, "Enter processEntryZoneEnrollRequest()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
-
-    //TODO: Might need to add into the list if needed - log it for now.
-    OC_LOG_V(INFO, TAG, "Just Joined - EUI:%s; NodeID:%s.", tokens[0], tokens[1]);
-
-    ret = TW_RESULT_OK;
-
-    OC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler().");
-    return ret;
-}
-
-TWResultCode TelMatchDescHandler(int count, char* tokens[])
-{
-    //Prompt:       MatchDesc:0B4A,00,01
-
-    OC_LOG_V(INFO, TAG, "Enter TelMatchDescHandler().");
-    if(!tokens || count <= 2)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
-
-    TWResultCode ret = TW_RESULT_ERROR;
-
-    if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        OC_LOG_V(ERROR, TAG, "MatchDesc prompt contained error status.");
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        //Create TWDevice
-        TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice));
-        if (device == NULL)
-        {
-            ret = TW_RESULT_ERROR_NO_MEMORY;
-        }
-        else
-        {
-            device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint));
-            if (device->endpointOfInterest == NULL)
-            {
-                OICFree(device);
-                ret = TW_RESULT_ERROR_NO_MEMORY;
-            }
-            else
-            {
-                //OICStrcpy(device->eui, SIZE_EUI, remoteEUI);
-                OICStrcpy(device->nodeId, SIZE_NODEID, tokens[0]);
-                OICStrcpy(device->endpointOfInterest->endpointId, SIZE_ENDPOINTID, tokens[2]);
-
-                if (g_FoundMatchedDeviceList == NULL)
-                {
-                    //Create a list of promptCount entries
-                    g_FoundMatchedDeviceList = (TWDeviceList*)OICMalloc(sizeof(TWDeviceList));
-                    if (g_FoundMatchedDeviceList == NULL)
-                    {
-                        OICFree(device->endpointOfInterest);
-                        OICFree(device);
-                        ret = TW_RESULT_ERROR_NO_MEMORY;
-                    }
-                    else
-                    {
-                        g_FoundMatchedDeviceList->count = 1;
-                        g_FoundMatchedDeviceList->deviceList =
-                                (TWDevice*)OICMalloc(sizeof(TWDevice));
-                        if (g_FoundMatchedDeviceList->deviceList == NULL)
-                        {
-                            OICFree(device->endpointOfInterest);
-                            OICFree(device);
-                            ret = TW_RESULT_ERROR_NO_MEMORY;
-                        }
-                        else
-                        {
-                            memcpy(g_FoundMatchedDeviceList->deviceList,
-                                   device,
-                                   sizeof(TWDevice));
-                            ret = TW_RESULT_OK;
-                        }
-                    }
-                }
-                else
-                {
-                    //Expand the list
-                    int newSize = sizeof(TWDevice) * (g_FoundMatchedDeviceList->count + 1);
-                    TWDevice* temp = (TWDevice*)realloc(g_FoundMatchedDeviceList->deviceList,
-                                                        newSize);
-                    if (temp == NULL)
-                    {
-                        OICFree(device->endpointOfInterest);
-                        OICFree(device);
-                        ret =TW_RESULT_ERROR_NO_MEMORY;
-                    }
-                    else
-                    {
-                        g_FoundMatchedDeviceList->deviceList = temp;
-
-                        //Add to the end of list
-                        int count = g_FoundMatchedDeviceList->count;
-                        memcpy(&g_FoundMatchedDeviceList->deviceList[count],
-                               device,
-                               sizeof(TWDevice));
-
-                        //Increase the count
-                        g_FoundMatchedDeviceList->count++;
-
-                        ret = TW_RESULT_OK;
-                    }
-                }
-            }
-        }
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryZoneEnrollRequest() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelSimpleDescHandler(int count, char* tokens[])
+TWResultCode processEntryEnrolled(TWEntry* entry)
 {
-    //AT+SIMPLEDESC:3746,3746,01
-    //      SEQ:97
-    //      OK
-    //
-    //      SimpleDesc:3746,00              <<<<<<<---------------------
-    //      EP:01
-    //      ProfileID:0104
-    //      DeviceID:0402v00
-    //      InCluster:0000,0001,0003,0402,0500,0020,0B05
-    //      OutCluster:0019
-    //      ACK:97
-
-    OC_LOG_V(INFO, TAG, "Enter TelSimpleDescHandler().");
-    if(!tokens || count <= 1)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    OC_LOG_V(INFO, TAG, "Enter processEntryEnrolled()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
-
-    if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        OC_LOG_V(ERROR, TAG, "SimpleDesc: prompt contained error status %s.", tokens[1]);
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
         ret = TW_RESULT_ERROR;
     }
     else
     {
-        if (strcmp(tokens[0], g_WIPDevice->nodeId) == 0)
-        {
-            OC_LOG_V(INFO, TAG, "Got simple descriptor for nodeid %s", tokens[0]);
-            ret = TW_RESULT_OK;
-        }
-        else
-        {
-            OC_LOG_V(ERROR, TAG,
-                     "Finding simple descriptor for non existing nodeid %s.", tokens[0]);
-            ret = TW_RESULT_ERROR;
-        }
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryEnrolled() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[])
+TWResultCode processEntryZoneStatus(TWEntry* entry)
 {
-    //AT+SIMPLEDESC:3746,3746,01
-    //      SEQ:97
-    //      OK
-    //
-    //      SimpleDesc:3746,00
-    //      EP:01
-    //      ProfileID:0104
-    //      DeviceID:0402v00
-    //      InCluster:0000,0001,0003,0402,0500,0020,0B05        <<<<<<<<--------------
-    //      OutCluster:0019
-    //      ACK:97
-
-    OC_LOG_V(INFO, TAG, "Enter TelSimpleDescInClusterHandler().");
-    TWResultCode ret = TW_RESULT_ERROR;
+    OC_LOG_V(INFO, TAG, "Enter processEntryZoneStatus()");
 
-    //Add found clusters for the node.
-    if (g_WIPDevice->endpointOfInterest->clusterList == NULL)
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        g_WIPDevice->endpointOfInterest->clusterList =
-                (TWClusterList*)OICCalloc(sizeof(TWClusterList), 1);
-        if (g_WIPDevice->endpointOfInterest->clusterList == NULL)
-        {
-            ret = TW_RESULT_ERROR_NO_MEMORY;
-        }
-        else
-        {
-            g_WIPDevice->endpointOfInterest->clusterList->clusterIds =
-                    (TWClusterId*)OICCalloc(sizeof(TWClusterId) * count, 1);
-            if (g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL)
-            {
-                OICFree(g_WIPDevice->endpointOfInterest->clusterList);
-                ret = TW_RESULT_ERROR_NO_MEMORY;
-            }
-            else
-            {
-                int i = 0;
-                for (; i < count; i++)
-                {
-                    OICStrcpy(g_WIPDevice->endpointOfInterest->clusterList->
-                                clusterIds[i].clusterId,
-                                SIZE_CLUSTERID,
-                                tokens[i]);
-
-                    OC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s",
-                             i,
-                             g_WIPDevice->endpointOfInterest->
-                             clusterList->clusterIds[i].clusterId);
-                }
-                g_WIPDevice->endpointOfInterest->clusterList->count = count;
-                ret = TW_RESULT_OK;
-            }
-        }
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        OC_LOG_V(ERROR, TAG, "Expected an empty cluster list.");
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryZoneStatus() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelWriteAttrHandler(int count, char* tokens[])
+TWResultCode processEntryAddressResponse(TWEntry* entry)
 {
-    //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
-    //      OK
-    //      WRITEATTR:3A3D,01,0003,,00
-
-    OC_LOG_V(INFO, TAG, "Enter TelWriteAttrHandler().");
-    if(!tokens || count <= 3)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    OC_LOG_V(INFO, TAG, "Enter processEntryAddressResponse()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
-
-    if (strcmp(tokens[3], AT_STR_ERROR_OK) == 0)
+    if (strcmp(entry->atErrorCode, AT_STR_ERROR_EVERYTHING_OK) != 0)
     {
-        ret = TW_RESULT_OK;
+        OC_LOG_V(ERROR, TAG, "TWEntry contains AT_ERROR: %s", entry->atErrorCode);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        ret = TW_RESULT_ERROR;
+        ret = HandleATResponse(entry);
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler().");
+    OC_LOG_V(INFO, TAG, "Leave processEntryAddressResponse() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[])
+TWResultCode Reset()
 {
-    //AT+READATR:F2D7,01,0,0402,0002
-    //      OK
-    //      TEMPERATURE:F2D7,01,0002,00,1770
-    //
-    //AT+READATR:F2D7,01,0,0402,0002
-    //      OK
-    //      ERROR:66
-
-    OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandlerTemperature().");
-    if(!tokens || count <= 4)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    OC_LOG_V(INFO, TAG, "Enter Reset()");
 
     TWResultCode ret = TW_RESULT_ERROR;
-
-    if (strcmp(tokens[3], AT_STR_ERROR_OK) != 0)
+    ret = TWIssueATCommand(g_plugin, AT_CMD_RESET);
+    if (ret == TW_RESULT_OK)
     {
-        OC_LOG_V(ERROR, TAG, "TEMPERATURE prompt contained error status.");
+        OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_RESET);
     }
     else
     {
-        // AttrInfo is 16-bit value representing (100 * Degrees Celsius)
-        // so 0x812 = 20.66 C = 69.188 F
-        if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
-        {
-            OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
-        }
-        OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[4]);
-        g_ZigBeeStatus.remoteAttributeValueRead =
-                (char*)OICMalloc(sizeof(char) * strlen(tokens[4]));
-        if (g_ZigBeeStatus.remoteAttributeValueRead == NULL)
-        {
-            ret = TW_RESULT_ERROR_NO_MEMORY;
-        }
-        else
-        {
-            strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[4]);
-            g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[4]);
-            ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
-        }
+        OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_RESET);
     }
-
-    OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature().");
-
+    OC_LOG_V(INFO, TAG, "Leave Reset() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelReadAttrHandler(int count, char* tokens[])
+TWResultCode CreatePAN()
 {
-    //AT+READATR:F2D7,01,0,0402,0002
-    //      OK
-    //      RESPATTR:<NodeID>,<EP>,<ClusterID>,<AttrID>,<Status>,<AttrInfo>
-    //
-    //AT+READATR:F2D7,01,0,0402,0002
+    /*
+    //at+n
+    //      +N=NoPAN
     //      OK
-    //      ERROR:66
 
-    OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandler().");
-    if(!tokens || count <= 5)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    (void)count;
+    //at+n
+    //      +N=COO,26,-6,7306,133F04EA669C6B24
+    //      OK
 
-    TWResultCode ret = TW_RESULT_ERROR;
+    //at+en
+    //      OK
+    //      JPAN:26,7306,133F04EA669C6B24
 
-    if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
+    //at+en
+    //      ERROR:28
+    */
+
+    OC_LOG_V(INFO, TAG, "Enter CreatePAN()");
+
+    TWResultCode twRet1 = TW_RESULT_UNKNOWN;
+    TWResultCode twRet2 = TW_RESULT_UNKNOWN;
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+    ret = TWIssueATCommand(g_plugin, AT_CMD_GET_NETWORK_INFO);
+    if (ret != TW_RESULT_OK)
     {
-        OC_LOG_V(ERROR, TAG, "READATTR prompt contained error status.");
+        OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_GET_NETWORK_INFO);
+    TWEntry* entry = NULL;
+    TWEntry* entry2 = NULL;
+    ret = TWDequeueEntry(g_plugin, &entry, TW_NETWORK_INFO);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_GET_NETWORK_INFO);
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_GET_NETWORK_INFO);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    ret = processEntry(entry);
+    if (ret == TW_RESULT_HAS_LOCAL_PAN)
+    {
+        OC_LOG_V(INFO, TAG, "Has local PAN.");
+        ret = TW_RESULT_OK;
+    }
+    else if (ret == TW_RESULT_NO_LOCAL_PAN)
+    {
+        OC_LOG_V(INFO, TAG, "Has no local PAN.");
+        ret = TWIssueATCommand(g_plugin, AT_CMD_ESTABLISH_NETWORK);
+        if (ret != TW_RESULT_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
+            goto exit;
+        }
+        OC_LOG_V(INFO, TAG, "Write %s", AT_CMD_ESTABLISH_NETWORK);
+
+        ret = TWDequeueEntry(g_plugin, &entry2, TW_JPAN);
+        if (ret != TW_RESULT_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", AT_CMD_ESTABLISH_NETWORK);
+            goto exit;
+        }
+        if (entry2 == NULL)
+        {
+            OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", AT_CMD_ESTABLISH_NETWORK);
+            ret = TW_RESULT_ERROR;
+            goto exit;
+        }
+        ret = processEntry(entry2);
+        if (ret == TW_RESULT_OK)
+        {
+            OC_LOG_V(INFO, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
+            g_ZigBeeStatus.state = ZB_STATE_INIT;
+            ret = TW_RESULT_OK;
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG, "processEntry - %s", AT_CMD_ESTABLISH_NETWORK);
+            ret = TW_RESULT_ERROR;
+        }
     }
     else
     {
-        if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
+        OC_LOG_V(ERROR, TAG, "processEntry - unexpected return code: %d", ret);
+        ret = TW_RESULT_ERROR;
+    }
+
+exit:
+    if (entry)
+    {
+        twRet1 = TWDeleteEntry(g_plugin, entry);
+        if(twRet1 != TW_RESULT_OK)
         {
-            OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
+            OC_LOG_V(ERROR, TAG, "TWDeleteEntry 1 - ret=%d", twRet1);
         }
-        OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[5]);
-        g_ZigBeeStatus.remoteAttributeValueRead =
-                (char*)OICMalloc(sizeof(char) * strlen(tokens[5]));
-        if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
+    }
+    if (entry2)
+    {
+        twRet2 = TWDeleteEntry(g_plugin, entry2);
+        if(twRet2 != TW_RESULT_OK)
         {
-            strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[5]);
-            g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[5]);
-            ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
+            OC_LOG_V(ERROR, TAG, "TWDeleteEntry 2 - ret=%d", twRet2);
         }
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandler().");
+    OC_LOG_V(INFO, TAG, "Leave CreatePan with ret=%d", ret);
+    return ret;
+}
 
+TWResultCode EnableJoin(bool isKeyEncrypted)
+{
+    //Ask:          AT+PJOIN
+    //Response:     OK
+
+    //Ask:          AT+PJOIN
+    //Response:     ERROR:70
+
+    (void)isKeyEncrypted;
+    isKeyEncrypted = false;         //TODO: for now - don't encrypt
+
+    TWResultCode ret = TW_RESULT_ERROR;
+    char* joinTimeHex = "0F";       //TODO: for now - 15 seconds
+    char* broadcast = "FFFC";
+
+    int size =  strlen(AT_CMD_PERMIT_JOIN) + strlen(joinTimeHex) +
+                SEPARATOR_LENGTH + strlen(broadcast) + 1;
+    char* cmdString = (char*)OICMalloc(size * sizeof(char));
+    if (cmdString == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
+    }
+    snprintf(cmdString, size, "%s%s%s%s",
+             AT_CMD_PERMIT_JOIN, joinTimeHex, SEPARATOR, broadcast);
+    ret = TWIssueATCommand(g_plugin, cmdString);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
+
+    sleep(15);  //must sleep here to permit joining for 15 seconds
+
+exit:
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave EnableJoin() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[])
+TWResultCode FindMatchNodes()
 {
-    //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
-    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+    //AT+MATCHREQ:0104,03,0003,0006,0402,00
+    //      OK
+    //      MatchDesc:0B4A,00,01
+
+    //AT+MATCHREQ:0104,03,0999,0999,0999,00
+    //      OK
+
+    OC_LOG_V(INFO, TAG, "Enter FindMatchNodes()");
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    char* profileHomeAutomation = "0104";
+    char* inClusterCount = "04";
+    char* outClusterCount = "00";
+
+    //TODO: add more clusters
+    char* clusterIdentify = "0003";
+    char* clusterOnOff = "0006";
+    char* clusterTemperatureMeasurement = "0402";
+    char* clusterIASZone = "0500";
+
+    int size = strlen(AT_CMD_MATCH_REQUEST) + strlen(profileHomeAutomation) +
+               SEPARATOR_LENGTH + strlen(inClusterCount) +
+               SEPARATOR_LENGTH + strlen(clusterIdentify) +
+               SEPARATOR_LENGTH + strlen(clusterOnOff) +
+               SEPARATOR_LENGTH + strlen(clusterTemperatureMeasurement) +
+               SEPARATOR_LENGTH + strlen(clusterIASZone) +
+               SEPARATOR_LENGTH + strlen(outClusterCount) + 1;
+
+    char* cmdString = (char*)OICMalloc(size * sizeof(char));
+    if (cmdString == NULL)
+    {
+        OC_LOG_V(INFO, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
+    }
+
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+                             AT_CMD_MATCH_REQUEST, profileHomeAutomation,
+                             SEPARATOR, inClusterCount,
+                             SEPARATOR, clusterIdentify,
+                             SEPARATOR, clusterOnOff,
+                             SEPARATOR, clusterTemperatureMeasurement,
+                             SEPARATOR, clusterIASZone,
+                             SEPARATOR, outClusterCount);
+    if(stringRet <= 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    ret = TWIssueATCommand(g_plugin, cmdString);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s.", cmdString);
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s.", cmdString);
+
+exit:
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave FindMatchNodes() with ret=%d", ret);
+    return ret;
+}
+
+TWResultCode FindClusters(char nodeId[], char endpoint[])
+{
+    /*
+    //AT+SIMPLEDESC:3746,3746,01
+    //      SEQ:97
+    //      OK
     //
-    //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
-    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+    //      SimpleDesc:3746,00
+    //      EP:01
+    //      ProfileID:0104
+    //      DeviceID:0402v00
+    //      InCluster:0000,0001,0003,0402,0500,0020,0B05
+    //      OutCluster:0019
     //
-    //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
-    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+    //      ACK:97
+    */
+
+    OC_LOG_V(INFO, TAG, "Enter FindClusters()");
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    OC_LOG_V(INFO, TAG, "Enter TelZCLDefaultResponseHandler().");
-    if(!tokens || count <= 4)
+    int size = strlen(AT_CMD_SIMPLE_DESC) + strlen(nodeId) +
+               SEPARATOR_LENGTH + strlen(nodeId) +
+               SEPARATOR_LENGTH + strlen(endpoint) + 1;
+
+    char* cmdString = (char*)OICMalloc(size * sizeof(char));
+    if (cmdString == NULL)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
     }
-    (void)count;
 
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s%s%s",
+                             AT_CMD_SIMPLE_DESC, nodeId,
+                             SEPARATOR, nodeId,
+                             SEPARATOR, endpoint);
+    if(stringRet <= 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    ret = TWIssueATCommand(g_plugin, cmdString);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
+
+    TWEntry* entry = NULL;
+    ret = TWDequeueEntry(g_plugin, &entry, TW_SIMPLEDESC);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+
+    ret = processEntry(entry);
+    if (ret == TW_RESULT_OK)
+    {
+        OC_LOG_V(INFO, TAG, "processEntry - %s", cmdString);
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+    }
+
+exit:
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave FindClusters() with ret=%d", ret);
+    return ret;
+}
+
+TWResultCode GetRemoteEUI(char *nodeId, char* outRemoteEUI)
+{
+    //AT+EUIREQ:< Address>,<NodeID>[,XX]
+    //  AddrResp:<errorcode>[,<NodeID>,<EUI64>]
+    //  AddrResp:00,15ED,000D6F00040574B8
+
+    OC_LOG_V(INFO, TAG, "Enter GetRemoteEUI()");
     TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    OC_LOG_V(INFO, TAG,
-             "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.",
-             tokens[0], tokens[1], tokens[2], tokens[3]);
+    int size = strlen(AT_CMD_REMOTE_EUI_REQUEST) + strlen(nodeId) +
+               SEPARATOR_LENGTH + strlen(nodeId) + 1;
+    char* cmdString = (char*)OICMalloc(size * sizeof(char));
+    if (cmdString == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
+    }
 
-    if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
+    int stringRet = snprintf(cmdString, size, "%s%s%s%s",
+                         AT_CMD_REMOTE_EUI_REQUEST, nodeId,
+                         SEPARATOR, nodeId);
+    if(stringRet <= 0)
     {
+        OC_LOG_V(ERROR, TAG, "Build command error.");
+        ret = OC_STACK_ERROR;
+        goto exit;
+    }
+    ret = TWIssueATCommand(g_plugin, cmdString);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Write %s", cmdString);
         ret = TW_RESULT_ERROR;
+        goto exit;
     }
-    else
+    OC_LOG_V(INFO, TAG, "Write %s", cmdString);
+
+    TWEntry* entry = NULL;
+    ret = TWDequeueEntry(g_plugin, &entry, TW_ADDRESS_RESPONSE);
+    if (ret != TW_RESULT_OK)
     {
-        ret = TW_RESULT_OK;
+        OC_LOG_V(ERROR, TAG, "TWDequeueEntry - %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    if (entry == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "TWEntry is NULL - %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelZCLDefaultResponseHandler().");
+    ret = processEntry(entry);
+    if (ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "processEntry - %s", cmdString);
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "Wanted   eui of NodeID=%s ", nodeId);
+    OC_LOG_V(INFO, TAG, "Received eui of g_WIPRemoteNodeId=%s ", g_WIPRemoteNodeId);
+    if (strcmp(nodeId, g_WIPRemoteNodeId) != 0)
+    {
+        OC_LOG_V(ERROR, TAG, "Received eui for an unexpected remote node id.");
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+
+    OC_LOG_V(INFO, TAG, "Remote NodeId:%s has EUI: %s \n",
+                        g_WIPRemoteNodeId, g_WIPRemoteEUI);
+    OICStrcpy(outRemoteEUI, SIZE_EUI, g_WIPRemoteEUI);
+
+    ret = TW_RESULT_OK;
 
+exit:
+    memset(g_WIPRemoteEUI, '\0', SIZE_EUI);
+    memset(g_WIPRemoteNodeId, '\0', SIZE_NODEID);
+    TWDeleteEntry(g_plugin, entry);
+    OICFree(cmdString);
+    OC_LOG_V(INFO, TAG, "Leave GetRemoteEUI() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[])
+TWResultCode HandleATResponse(TWEntry* entry)
 {
-    //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
-    //      DRLOCRSP:<nodeID>,<ep>,<status>
-    //      or
-    //      DRUNLOCKRSP:<nodeID>,<ep>,<status>
+    OC_LOG_V(INFO, TAG, "Enter HandleATResponse()");
+
+    TWResultCode ret = TW_RESULT_ERROR;
 
-    OC_LOG_V(INFO, TAG, "Enter TelSwitchDoorLockStateHandler().");
-    if(!tokens || count <= 4)
+    int32_t i = 0;
+    for (; i < entry->count; i++)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        uint32_t k = 0;
+        for (; k < sizeof(g_TWATResultHandlerPairArray)/sizeof(TWATResultHandlerPair); ++k)
+        {
+            const char* line = (entry)->lines[i].line;
+            if (strncmp(line,
+                        g_TWATResultHandlerPairArray[k].resultTxt,
+                        strlen(g_TWATResultHandlerPairArray[k].resultTxt)
+                        ) == 0)
+            {
+                char* tokens[ARRAY_LENGTH] = {};
+                const char* delimiters = ",\r\n";
+                int paramCount = Tokenize((entry)->lines[i].line +
+                                           strlen(g_TWATResultHandlerPairArray[k].resultTxt),
+                                           delimiters, tokens);
+                if (paramCount > 0)
+                {
+                    ret = g_TWATResultHandlerPairArray[k].handler(paramCount, tokens);
+                }
+
+                int n = 0;
+                for (; n < paramCount; n++)
+                {
+                    OICFree(tokens[n]);
+                }
+
+                break;
+            }
+        }
     }
-    (void)count;
+
+    OC_LOG_V(INFO, TAG, "Leave HandleATResponse() with ret=%d", ret);
+    return ret;
+}
+
+//-----------------------------------------------------------------------------
+// Internal functions - AT Response/Prompt Handlers
+//-----------------------------------------------------------------------------
+
+TWResultCode TelAddressResponseHandler(int count, char* tokens[])
+{
+    //AT+EUIREQ:< Address>,<NodeID>[,XX]
+    //  AddrResp:<errorcode>[,<NodeID>,<EUI64>]
+    //  AddrResp:00,15ED,000D6F00040574B8
+
+    OC_LOG_V(INFO, TAG, "Enter TelAddressResponseHandler()");
 
     TWResultCode ret = TW_RESULT_UNKNOWN;
-    if (strcmp(tokens[2], AT_STR_ERROR_OK) != 0)
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_ADDRESS_RESPONSE)
     {
-        OC_LOG_V(ERROR, TAG,
-                 "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.", tokens[4]);
-        ret = TW_RESULT_ERROR;
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
     }
     else
     {
-        OC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.",
-                 tokens[0], tokens[1]);
-        ret = TW_RESULT_OK;
+        if (strcmp(tokens[0], AT_STR_ERROR_OK) != 0)
+        {
+            OC_LOG_V(ERROR, TAG, "AddrResp prompt contained error status.");
+            ret = TW_RESULT_ERROR;
+        }
+        else
+        {
+            OICStrcpy(g_WIPRemoteNodeId, SIZE_NODEID, tokens[1]);
+            OICStrcpy(g_WIPRemoteEUI, SIZE_EUI, tokens[2]);
+            OC_LOG_V(INFO, TAG, "Received eui %s for g_WIPRemoteNodeId=%s ",
+                     g_WIPRemoteEUI,
+                     g_WIPRemoteNodeId);
+            ret = TW_RESULT_OK;
+        }
+    }
+
+    OC_LOG_V(INFO, TAG, "Leave TelAddressResponseHandler() with ret=%d", ret);
+    return ret;
+}
+
+TWResultCode TelNetworkInfoHandler(int count, char* tokens[])
+{
+    // Ask:         AT+N
+    // Response:    +N=COO,24,-6,9726,12BB200F073AB573
+    //                          or
+    //              +N=NoPAN
+    //
+    //              +N=<devicetype>,<channel>,<power>,<PANID>,<EPANID>
+
+    OC_LOG_V(INFO, TAG, "Enter TelNetworkInfoHandler()");
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    if(!tokens ||
+       ((count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_1) &&
+        (count != RESPONSE_PARAMS_COUNT_NETWORK_INFO_5)))
+    {
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
+    }
+
+    int i = 0;
+    for (; i < count; ++i)
+    {
+        if (tokens[i] != NULL)
+        {
+            OC_LOG_V(INFO, TAG, "Token[%d] = %s", i, tokens[i]);
+        }
+    }
+
+    char* temp = tokens[0];
+    if (strcmp(temp, "NoPAN") == 0)
+    {
+        OC_LOG_V(INFO, TAG, "It is NoPan.");
+        ret = TW_RESULT_NO_LOCAL_PAN;
+        goto exit;
+    }
+
+    OC_LOG_V(INFO, TAG, "Already have an established network.");
+    ret = AsciiHexToValue(tokens[3], strlen(tokens[3]), &g_ZigBeeStatus.panId);
+    if(ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId");
+        goto exit;
+    }
+    ret = AsciiHexToValue(tokens[4], strlen(tokens[4]), &g_ZigBeeStatus.extPanId);
+    if(ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId");
+        goto exit;
     }
+    OC_LOG_V(INFO, TAG, "PanId=%" PRId64 , g_ZigBeeStatus.panId);
+    OC_LOG_V(INFO, TAG, "ExtPanId=%" PRId64 , g_ZigBeeStatus.extPanId);
+    OC_LOG_V(INFO, TAG, "PanId=%s", tokens[3]);
+    OC_LOG_V(INFO, TAG, "ExtPanId=%s", tokens[4]);
 
-    OC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler().");
+    OC_LOG_V(INFO, TAG, "TelNetworkInfoHandler set ExtPanId to %08X%08X",
+             (unsigned int)(g_ZigBeeStatus.extPanId >> 32),
+             (unsigned int)(g_ZigBeeStatus.extPanId & 0xFFFFFFFF));
 
+    ret = TW_RESULT_HAS_LOCAL_PAN;
+
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelNetworkInfoHandler() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[])
+TWResultCode TelJpanHandler(int count, char* tokens[])
 {
-    //ZENROLLREQ:<NodeID>,<EndPoint>,<ZoneType>,<ManufactureCode>
+    //Ask:        AT+EN:[<channel>],[<POWER>],[<PANID>]
+    //Response:   JPAN:<channel>,<PANID>,<EPANID>
 
-    OC_LOG_V(INFO, TAG, "Enter TelZoneEnrollRequestHandler().");
-    if(!tokens || count <= 3)
+    OC_LOG_V(INFO, TAG, "Enter TelJpanHandler()");
+
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_JPAN)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    (void)count;
 
-    TWResultCode ret = TW_RESULT_OK;
+    ret = AsciiHexToValue(tokens[1], strlen(tokens[1]), &g_ZigBeeStatus.panId);
+    if(ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "AsciiHexToValue - panId");
+        goto exit;
+    }
+    ret = AsciiHexToValue(tokens[2], strlen(tokens[2]), &g_ZigBeeStatus.extPanId);
+    if(ret != TW_RESULT_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "AsciiHexToValue - extPanId");
+        goto exit;
+    }
+    OC_LOG_V(INFO, TAG, "PanId = %" PRId64 "\n", g_ZigBeeStatus.panId);
+    OC_LOG_V(INFO, TAG, "ExtPanId = %" PRId64 "\n", g_ZigBeeStatus.extPanId);
+    ret = TW_RESULT_NEW_LOCAL_PAN_ESTABLISHED;
 
-    OC_LOG_V(INFO, TAG, "Received zone request from:");
-    OC_LOG_V(INFO, TAG, "Node:%s", tokens[0]);
-    OC_LOG_V(INFO, TAG, "EP:%s", tokens[1]);
-    OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[2]);
-    OC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[3]);
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelJpanHandler() with ret=%d", ret);
+    return ret;
+}
+
+TWResultCode TelEndDeviceJoinHandler(int count, char* tokens[])
+{
+    //Ask:      AT+PJOIN
+    //
+    //Prompt:   RFD:<IEEE Address>,<NodeID>
+    //Prompt:   FFD:<IEEE Address>,<NodeID>
+    //Prompt:   SED:<IEEE Address>,<NodeID>
+    //Prompt:   ZED:<IEEE Address>,<NodeID>
+
+    OC_LOG_V(INFO, TAG, "Enter TelEndDeviceJoinHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_DEVICE_JOINED)
+    {
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
+    }
+
+    //TODO: Might need to add into the list if needed - log it for now.
+    OC_LOG_V(INFO, TAG, "Just Joined - EUI:%s; NodeID:%s.\n", tokens[0], tokens[1]);
+    ret = TW_RESULT_OK;
+
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelEndDeviceJoinHandler() with ret=%d", ret);
+    return ret;
+}
+
+TWResultCode TelMatchDescHandler(int count, char* tokens[])
+{
+    //Prompt:       MatchDesc:0B4A,00,01
+
+    OC_LOG_V(INFO, TAG, "Enter TelMatchDescHandler()");
+    TWResultCode ret = TW_RESULT_ERROR;
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_MATCH_DESC)
+    {
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
+    }
+
+    if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
+    {
+        OC_LOG_V(INFO, TAG, "MatchDesc prompt contained error status.");
+        ret = TW_RESULT_ERROR;
+        goto exit;
+    }
+    else
+    {
+        char remoteEUI[SIZE_EUI];
+        ret = GetRemoteEUI(tokens[0], remoteEUI);
+        if (ret != TW_RESULT_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "GetRemoteEUI()");
+            goto exit;
+        }
+        else
+        {
+            //Step 1: Create TWDevice
+            TWDevice* device = (TWDevice*)OICCalloc(1, sizeof(TWDevice));
+            if (device == NULL)
+            {
+                ret = TW_RESULT_ERROR_NO_MEMORY;
+                goto exit;
+            }
+            else
+            {
+                device->endpointOfInterest = (TWEndpoint*)OICCalloc(1, sizeof(TWEndpoint));
+                if (device->endpointOfInterest == NULL)
+                {
+                    OICFree(device);
+                    ret = TW_RESULT_ERROR_NO_MEMORY;
+                }
+                else
+                {
+                    OICStrcpy(device->eui, SIZE_EUI, remoteEUI);
+                    OICStrcpy(device->nodeId, SIZE_NODEID, tokens[0]);
+                    OICStrcpy(device->endpointOfInterest->endpointId, SIZE_ENDPOINTID, tokens[2]);
+                    g_WIPDevice = device;
+
+                    //Step 2: Add to list
+                    if (g_FoundMatchedDeviceList == NULL)
+                    {
+                        //Create a list of promptCount entries
+                        g_FoundMatchedDeviceList = (TWDeviceList*)OICMalloc(sizeof(TWDeviceList));
+                        if (g_FoundMatchedDeviceList == NULL)
+                        {
+                            OICFree(device->endpointOfInterest);
+                            OICFree(device);
+                            ret = TW_RESULT_ERROR_NO_MEMORY;
+                        }
+                        else
+                        {
+                            g_FoundMatchedDeviceList->count = 1;
+                            g_FoundMatchedDeviceList->deviceList =
+                                    (TWDevice*)OICMalloc(sizeof(TWDevice));
+                            if (g_FoundMatchedDeviceList->deviceList == NULL)
+                            {
+                                OICFree(device->endpointOfInterest);
+                                OICFree(device);
+                                ret = TW_RESULT_ERROR_NO_MEMORY;
+                            }
+                            else
+                            {
+                                memcpy(g_FoundMatchedDeviceList->deviceList,
+                                       device,
+                                       sizeof(TWDevice));
+                                ret = TW_RESULT_OK;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        //Expand the list
+                        int newSize = sizeof(TWDevice) * (g_FoundMatchedDeviceList->count + 1);
+                        TWDevice* temp = (TWDevice*)realloc(g_FoundMatchedDeviceList->deviceList,
+                                                            newSize);
+                        if (temp == NULL)
+                        {
+                            OICFree(device->endpointOfInterest);
+                            OICFree(device);
+                            ret =TW_RESULT_ERROR_NO_MEMORY;
+                        }
+                        else
+                        {
+                            g_FoundMatchedDeviceList->deviceList = temp;
+
+                            //Add to the end of list
+                            int count = g_FoundMatchedDeviceList->count;
+                            memcpy(&g_FoundMatchedDeviceList->deviceList[count],
+                                   device,
+                                   sizeof(TWDevice));
 
-    OC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler().");
+                            //Increase the count
+                            g_FoundMatchedDeviceList->count++;
 
-    return ret;
+                            ret = TW_RESULT_OK;
+                        }
+                    }
+                }
+            }
+        }
+    }
 
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelMatchDescHandler() with ret=%d", ret);
+    return ret;
 }
 
-TWResultCode TelEnrolledHandler(int count, char* tokens[])
+TWResultCode TelSimpleDescHandler(int count, char* tokens[])
 {
-    //ENROLLED:<ZID>,<ZoneType>,<EUI>
+    //AT+SIMPLEDESC:3746,3746,01
+    //      SEQ:97
+    //      OK
+    //
+    //      SimpleDesc:3746,00              <<<<<<<---------------------
+    //      EP:01
+    //      ProfileID:0104
+    //      DeviceID:0402v00
+    //      InCluster:0000,0001,0003,0402,0500,0020,0B05
+    //      OutCluster:0019
+    //      ACK:97
+
+    OC_LOG_V(INFO, TAG, "Enter TelSimpleDescHandler().");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    OC_LOG_V(INFO, TAG, "Enter TelEnrolledHandler().");
-    if(!tokens || count <= 2)
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_SIMPLE_DESC)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    (void)count;
-
-    TWResultCode ret = TW_RESULT_OK;
 
-    OC_LOG_V(INFO, TAG, "Received zone request from:");
-    OC_LOG_V(INFO, TAG, "ZID:%s", tokens[0]);
-    OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[1]);
-    OC_LOG_V(INFO, TAG, "EUI:%s", tokens[2]);
-
-    TWEnrollee enrollee;
-    OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[0]);
-    OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[1]);
-    OICStrcpy(enrollee.eui, SIZE_EUI, tokens[2]);
-
-    if (g_EnrollmentSucceedCallback != NULL)
+    if (g_WIPDevice == NULL)
     {
-        g_EnrollmentSucceedCallback(&enrollee);
+        OC_LOG_V(ERROR, TAG,
+                 "Receive simple descriptor unexpectedly - %s", tokens[0]);
+        ret = TW_RESULT_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler().");
+    if (strcmp(tokens[1], AT_STR_ERROR_OK) != 0)
+    {
+        OC_LOG_V(ERROR, TAG, "SimpleDesc: prompt contained error status %s.", tokens[1]);
+        ret = TW_RESULT_ERROR;
+    }
+    else
+    {
+        if (strcmp(tokens[0], g_WIPDevice->nodeId) == 0)
+        {
+            OC_LOG_V(INFO, TAG, "Got simple descriptor for nodeid %s", tokens[0]);
+            ret = TW_RESULT_OK;
+        }
+        else
+        {
+            OC_LOG_V(ERROR, TAG,
+                     "Finding simple descriptor for non existing nodeid %s.", tokens[0]);
+            ret = TW_RESULT_ERROR;
+        }
+    }
 
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelSimpleDescHandler() with ret=%d", ret);
     return ret;
 }
 
-TWResultCode TelZoneStatusHandler(int count, char* tokens[])
+TWResultCode TelSimpleDescInClusterHandler(int count, char* tokens[])
 {
-    //ZONESTATUS:<NodeID>,<EP>,<ZoneStatus>,<ExtendStatus>[,<ZoneID>,<Delay>]
-    //ZONESTATUS:5FBA,01,0021,00,01,00AF
+    //AT+SIMPLEDESC:3746,3746,01
+    //      SEQ:97
+    //      OK
+    //
+    //      SimpleDesc:3746,00
+    //      EP:01
+    //      ProfileID:0104
+    //      DeviceID:0402v00
+    //      InCluster:0000,0001,0003,0402,0500,0020,0B05        <<<<<<<<--------------
+    //      OutCluster:0019
+    //      ACK:97
+
+    OC_LOG_V(INFO, TAG, "Enter TelSimpleDescInClusterHandler()");
+    TWResultCode ret = TW_RESULT_ERROR;
 
-    OC_LOG_V(INFO, TAG, "Enter TelZoneStatusHandler().");
-    if(!tokens || count <= 3)
+    if (!tokens || count < RESPONSE_PARAMS_COUNT_SIMPLE_DESC_IN_CLUSTER_MIN )
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+               goto exit;
     }
-    TWResultCode ret = TW_RESULT_OK;
-
-    TWUpdate update;
-    OICStrcpy(update.nodeId, SIZE_NODEID, tokens[0]);
-    OICStrcpy(update.endpoint, SIZE_NODEID, tokens[1]);
-    OICStrcpy(update.status, SIZE_NODEID, tokens[2]);
-    OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[3]);
 
-    if (count == 6)
+    if (g_WIPDevice == NULL)
     {
-        OICStrcpy(update.zoneId, SIZE_NODEID, tokens[4]);
-        OICStrcpy(update.delay, SIZE_NODEID, tokens[5]);
+        OC_LOG_V(ERROR, TAG,
+                 "Receive simple descriptor unexpectedly - %s", tokens[0]);
+        ret = TW_RESULT_ERROR;
+        goto exit;
     }
 
-    if (g_DeviceStatusUpdateCallback != NULL)
+    if (g_WIPDevice->endpointOfInterest->clusterList != NULL)
     {
-        g_DeviceStatusUpdateCallback(&update);
+        OC_LOG_V(ERROR, TAG, "Expected an empty cluster list.");
+        ret = TW_RESULT_ERROR;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler().");
-
-    return ret;
-}
-
-//-----------------------------------------------------------------------------
-// Internal functions - Helpers
-//-----------------------------------------------------------------------------
-
-/**
- *
- * Tokenize 'input' parameter by 'delimiters' into 'output' array.
- *
- */
-int Tokenize(const char *input, const char* delimiters, char* output[])
-{
-    OC_LOG_V(INFO, TAG, "Enter Tokenize()");
-
-    if (output == NULL)
+    //Add found clusters for the node.
+    g_WIPDevice->endpointOfInterest->clusterList =
+            (TWClusterList*)OICMalloc(sizeof(TWClusterList));
+    if (g_WIPDevice->endpointOfInterest->clusterList == NULL)
     {
-        OC_LOG_V(INFO, TAG, "Invalid parameter.");
-        return -1;
+        OC_LOG_V(ERROR, TAG, "No Memory - clusterList");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
     }
 
-    int length = strlen(input);
-    char * str = (char *) OICCalloc(1, length + 1);
-    OICStrcpy(str, length+1, input);
+    g_WIPDevice->endpointOfInterest->clusterList->clusterIds =
+            (TWClusterId*)OICMalloc(sizeof(TWClusterId) * count);
+    if (g_WIPDevice->endpointOfInterest->clusterList->clusterIds == NULL)
+    {
+        OICFree(g_WIPDevice->endpointOfInterest->clusterList);
+        OC_LOG_V(ERROR, TAG, "No Memory - clusterIds");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+        goto exit;
+    }
 
-    char* savePtr = NULL;
-    char* p   = strtok_r(str, delimiters, &savePtr);
-    int index = 0;
-    while (p && index <= ARRAY_LENGTH)
+    int i = 0;
+    for (; i < count; i++)
     {
-        int size = strlen(p) + 1;   //for null char
-        output[index] = (char*)OICCalloc(size, sizeof(char));
-        OICStrcpy(output[index], size, p);
+        OICStrcpy(g_WIPDevice->endpointOfInterest->clusterList->
+                    clusterIds[i].clusterId,
+                    SIZE_CLUSTERID,
+                    tokens[i]);
 
-        p = strtok_r (NULL, delimiters, &savePtr);
-        index++;
+        OC_LOG_V(INFO, TAG, "ClusterIds[%d]=%s",
+                 i,
+                 g_WIPDevice->endpointOfInterest->
+                 clusterList->clusterIds[i].clusterId);
     }
+    g_WIPDevice->endpointOfInterest->clusterList->count = count;
+    ret = TW_RESULT_HAS_CLUSTERS;
 
-    OICFree(str);
-    OC_LOG_V(INFO, TAG, "Leave Tokenize()");
-    return index;
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelSimpleDescInClusterHandler() with ret=%d", ret);
+    return ret;
 }
 
-int AsciiToHex(char c)
+TWResultCode TelWriteAttrHandler(int count, char* tokens[])
 {
-    int num = (int) c;
-    if(c >= '0' && c <= '9')
-    {
-        return num - '0';
-    }
+    //AT+WRITEATR:3A3D,01,0,0003,0000,21,00
+    //      OK
+    //      WRITEATTR:3A3D,01,0003,,00
+    //
+    //AT+WRITEATR:B826,01,0,0500,0010,F0,000D6F0000D59E92
+    //      OK
+    //      WRITEATTR:B826,01,0500,0010,70
 
-    if(num >= 'A' && num <= 'F')
-    {
-        return num - 'A' + 10;
-    }
-    return -1;
-}
+    OC_LOG_V(INFO, TAG, "Enter TelWriteAttrHandler()");
 
-TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value)
-{
-    if(!hexString || !value || length < 0)
+    TWResultCode ret = TW_RESULT_ERROR;
+
+    if(!tokens ||
+       (count < RESPONSE_PARAMS_COUNT_WRITE_ATTR_4) ||
+       (count > RESPONSE_PARAMS_COUNT_WRITE_ATTR_5))
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    int retVal = AsciiToHex(hexString[0]);
-    if(retVal == -1)
+
+    if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_4)
     {
-        OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
-        return TW_RESULT_ERROR;
+        if (strcmp(tokens[3], AT_STR_ERROR_OK) == 0)
+        {
+            ret = TW_RESULT_OK;
+        }
     }
-    *value = (uint64_t)retVal;
-    for (int i = 1; i < length*2; ++i)
+    else if (count == RESPONSE_PARAMS_COUNT_WRITE_ATTR_5)
     {
-        if (sizeof(hexString) > (uint32_t)i)
+        if (strcmp(tokens[4], AT_STR_ERROR_INVALID_OP) == 0)
         {
-            *value <<= 4;
-            retVal = AsciiToHex(hexString[i]);
-            if(retVal == -1)
-            {
-                OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
-                return TW_RESULT_ERROR;
-            }
-            *value |= (uint64_t)retVal;
+            ret = TW_RESULT_ERROR_INVALID_OP;
         }
     }
-    return TW_RESULT_OK;
+
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelWriteAttrHandler() with ret=%d", ret);
+    return ret;
 }
 
-/**
- *
- * Apply interface attribute values to terminal settings.
- *
- */
-int SetTerminalInfo(int fd, int speed, int parity, int shouldBlock)
+TWResultCode TelReadAttrHandlerTemperature(int count, char* tokens[])
 {
-    OC_LOG_V(INFO, TAG, "Enter SetTerminalInfo()");
+    //AT+READATR:F2D7,01,0,0402,0002
+    //      OK
+    //      TEMPERATURE:F2D7,01,0002,00,1770
+    //
+    //AT+READATR:F2D7,01,0,0402,0002
+    //      OK
+    //      ERROR:66
+
+    OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandlerTemperature().");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    int ret = 0;
-    struct termios terminalInfo = {0, 0, 0, 0, 0, 0, 0};
-    ret = tcgetattr(fd, &terminalInfo);
-    if (ret != 0)
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_TEMPERATURE)
     {
-        OC_LOG_V(ERROR, TAG, "tcgetattr() - error=%d", ret);
-        ret = -1;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
         goto exit;
     }
 
-    ret = cfsetispeed (&terminalInfo, speed);
-    if (ret != 0)
+    if (strcmp(tokens[3], AT_STR_ERROR_OK) != 0)
     {
-        OC_LOG_V(ERROR, TAG, "cfsetispeed() - error=%d", ret);
-        ret = -1;
+        OC_LOG_V(ERROR, TAG, "TEMPERATURE prompt contained error status.");
+        ret = TW_RESULT_ERROR;
         goto exit;
     }
 
-    ret = cfsetospeed (&terminalInfo, speed);
-    if (ret != 0)
+    // AttrInfo is 16-bit value representing (100 * Degrees Celsius)
+    // so 0x812 = 20.66 C = 69.188 F
+    if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
     {
-        OC_LOG_V(ERROR, TAG, "cfsetospeed() - error=%d", ret);
-        ret = -1;
-        goto exit;
+        OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
+        g_ZigBeeStatus.remoteAttributeValueRead = NULL;
     }
-
-    terminalInfo.c_cflag = (terminalInfo.c_cflag & ~CSIZE);     //byte size
-    terminalInfo.c_cflag |= CS8;        //byte size is 8
-
-    terminalInfo.c_cflag &= ~PARENB;    //no parity
-    terminalInfo.c_cflag |= parity;     //no parity
-
-    terminalInfo.c_cflag &= ~CSTOPB;    //1 stop bit
-
-    terminalInfo.c_cflag |= CREAD;      //enable the receiver
-
-    //Input Control Settings
-    terminalInfo.c_iflag &= ~IGNBRK;    //break condition
-
-    //Local Mode Settings
-    terminalInfo.c_lflag = 0;
-
-    // whether to block on read and read time-out
-    terminalInfo.c_cc[VMIN]  = (shouldBlock >= 1) ? 1 : 0;
-    terminalInfo.c_cc[VTIME] = 5;
-
-    //Input Control Settings
-    terminalInfo.c_oflag = 0;
-
-    if (tcsetattr (fd, TCSANOW, &terminalInfo) != 0)
+    OC_LOG_V(INFO, TAG, "Read Attribute Value: %s", tokens[4]);
+    g_ZigBeeStatus.remoteAttributeValueRead =
+            (char*)OICMalloc(sizeof(char) * strlen(tokens[4]));
+    if (g_ZigBeeStatus.remoteAttributeValueRead == NULL)
+    {
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
+    }
+    else
     {
-        OC_LOG_V(ERROR, TAG, "tcsetattr");
-        ret = -1;
+        strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[4]);
+        g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[4]);
+        ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
     }
 
 exit:
-    OC_LOG_V(INFO, TAG, "Leave SetTerminalInfo() with ret=%d", ret);
+    OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandlerTemperature() with ret=%d", ret);
     return ret;
 }
 
-/**
- *
- * Issues an AT Command to the Telegesis Dongle. Waits for response unless
- * a timeout is specified. Blocks until operation is completed. Responses are
- * in placed responseArray, while prompts are placed in promptArray.
- *
- * @param[out] atErrorCode The AT Error code received as Hex. 0 on success,
- *                       otherwise refer to Telegesis manual.
- * @param[out] responseArray Array corresponding to response lines received in
- *                           the buffer during a write/read. (ie. A synchronous
- *                           AT result.)
- * @param[out] promptArray Array corresponding to prompt lines received in
- *                         the buffer post write/read. (ie. An asynchronous AT
- *                         result.)
- * @param[out] responseCount The number of responses in the response array.
- * @param[out] promptCount The number of prompts in the prompt array.
- * @param[in] command The AT Command you wish to issue.
- * @param[in] timeout The allotted time (seconds) you expect the AT Command's
- *                    prompt results to reach the buffer.
- *
- */
-TWResultCode IssueATCommand(const char * command,
-                            uint8_t timeout,
-                            uint64_t * atErrorCode,
-                            char * responseArray[],
-                            char * promptArray[],
-                            uint8_t * responseCount,
-                            uint8_t * promptCount)
+TWResultCode TelReadAttrHandler(int count, char* tokens[])
 {
-    TWResultCode ret = TW_RESULT_ERROR;
+    //AT+READATR:F2D7,01,0,0402,0002
+    //      OK
+    //      RESPATTR:<NodeID>,<EP>,<ClusterID>,<AttrID>,<Status>,<AttrInfo>
+    //
+    //AT+READATR:F2D7,01,0,0402,0002
+    //      OK
+    //      ERROR:66
 
-    ret = WriteBuffer(command);
-    if(ret != TW_RESULT_OK)
-    {
-        OC_LOG_V(ERROR, TAG, "Failed to write to buffer with result: %d", ret);
-        return ret;
-    }
+    OC_LOG_V(INFO, TAG, "Enter TelReadAttrHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    ret = ReadBuffer(atErrorCode,
-                     responseArray,
-                     responseCount,
-                     command,
-                     0);
-    if(ret != TW_RESULT_OK)
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_RESPATTR)
     {
-        OC_LOG_V(ERROR, TAG, "Failed to read from buffer with result: %d", ret);
-        return ret;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    if(timeout != 0)
+
+    if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
     {
-        sleep(timeout);
-        ret = ReadBuffer(atErrorCode,
-                         promptArray,
-                         promptCount,
-                         NULL,
-                         timeout);
-        if(ret != TW_RESULT_OK)
-        {
-            OC_LOG_V(ERROR, TAG, "Failed to read from buffer with result: %d", ret);
-            return ret;
-        }
+        OC_LOG_V(INFO, TAG, "READATTR prompt contained error status.");
+        ret = TW_RESULT_ERROR;
+        goto exit;
     }
-    return ret;
-}
 
-/**
- *
- * Returns file descriptor by reference based on the global comPort specified
- * at the top of this file.
- *
- * @param[out] fd The file descriptor associated with the comport specified.
- *
- */
-TWResultCode OpenPort(int * fd)
-{
-    if(g_port == NULL)
+    if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
     {
-        OC_LOG_V(ERROR, TAG, "No port specified.");
-        return TW_RESULT_ERROR_INVALID_PORT;
+        OICFree(g_ZigBeeStatus.remoteAttributeValueRead);
     }
-    if(!fd)
+    OC_LOG_V(INFO, TAG, "Read Attribute Value: %s.", tokens[5]);
+    g_ZigBeeStatus.remoteAttributeValueRead =
+            (char*)OICMalloc(sizeof(char) * strlen(tokens[5]));
+    if (g_ZigBeeStatus.remoteAttributeValueRead != NULL)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        strcpy(g_ZigBeeStatus.remoteAttributeValueRead, tokens[5]);
+        g_ZigBeeStatus.remoteAtrributeValueReadLength = strlen(tokens[5]);
+        ret = TW_RESULT_REMOTE_ATTR_HAS_VALUE;
     }
-    int tw_fd = open(g_port, O_RDWR | O_NOCTTY | O_SYNC);
-    *fd = tw_fd;
-    if(tw_fd <= 0)
+    else
     {
-        OC_LOG_V(ERROR, TAG, "Could not open port. Errno is: %d", errno);
-        return TW_RESULT_ERROR;
+        OC_LOG_V(ERROR, TAG, "No Memory");
+        ret = TW_RESULT_ERROR_NO_MEMORY;
     }
 
-    // set speed to 19,200 bps, 8n1 (no parity), no block
-    SetTerminalInfo(tw_fd, DEVICE_BAUDRATE, 0, 0);
-
-    return TW_RESULT_OK;
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelReadAttrHandler().\n");
+    return ret;
 }
 
-/**
- *
- * Closes port based on the specified file descriptor.
- *
- *  Returns TW_RESULT_OK on success.
- *
- * @param[in] The file descriptor to be closed.
- *
- */
-TWResultCode ClosePort(int fd)
+TWResultCode TelZCLDefaultResponseHandler(int count, char* tokens[])
 {
-    int ret = close(fd);
-    if(ret != 0)
+    //AT+RONOFF:<Address>,<EP>,<SendMode>[,<ON/OFF>]
+    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+    //
+    //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
+    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+    //
+    //AT+LCMVTOLEV:<Address>,<EP>,<SendMode>,<ON/OFF>,<LevelValue>,<TransTime>
+    //      DFTREP:<NodeID>,<EP>,<ClusterID>,<CMD>,<Status>
+
+    OC_LOG_V(INFO, TAG, "Enter TelZCLDefaultResponseHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_DFTREP)
     {
-        OC_LOG_V(ERROR, TAG, "Could not close port. Errno is: %d", errno);
-        return TW_RESULT_ERROR;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    return TW_RESULT_OK;
-}
 
-bool IsThisAValidLine(char * singleLine, bool * endControlHit, uint64_t * atErrorCode)
-{
-    if(!singleLine || !endControlHit || !atErrorCode)
+    OC_LOG_V(INFO, TAG,
+             "DFTREP prompt succeed for NodeId:%s, EP:%s, ClusterId:%s, CMD:%s.\n",
+             tokens[0], tokens[1], tokens[2], tokens[3]);
+
+    if (strcmp(tokens[4], AT_STR_ERROR_OK) != 0)
     {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
+        ret = TW_RESULT_ERROR;
     }
-    size_t singleLineSize = strlen(singleLine);
-    int i = 0;
-    size_t endStrSize = 0;
-    size_t strSize = 0;
-    TWResultCode ret = TW_RESULT_ERROR;
-    for(; i<TW_ENDCONTROL_MAX_VALUE; i++)
+    else
     {
-        endStrSize = strlen(g_TWEndMessageMap[i].endStr);
-        strSize = singleLineSize >= endStrSize ? endStrSize : singleLineSize;
-        // Found a single EndControl string.
-        if (strncmp(singleLine, g_TWEndMessageMap[i].endStr, strSize) == 0)
-        {
-            //endControlHit = true;
-            if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_OK)
-            {
-               *atErrorCode = 0x0000;
-               *endControlHit = true;
-            }
-            else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_ERROR)
-            {
-                ret = AsciiHexToValue(&singleLine[strSize],
-                                      strlen(&singleLine[strSize])-1,
-                                      atErrorCode);
-                if(ret != TW_RESULT_OK)
-                {
-                    return false;
-                }
-                *endControlHit = true;
-            }
-            else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_SEQ)
-            {
-                //endControlHit = false;
-            }
-            else if (g_TWEndMessageMap[i].endControl == TW_ENDCONTROL_ACK)
-            {
-                //endControlHit = false;
-            }
-            return false;
-            //break;
-        }
+        ret = TW_RESULT_OK;
     }
-    return true;
 
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelZCLDefaultResponseHandler()");
+    return ret;
 }
 
-char * myStrTok(char* readData, const char* tokens, bool * endControlHit,
-                 uint64_t * atErrorCode, char ** savePtr)
+TWResultCode TelSwitchDoorLockStateHandler(int count, char* tokens[])
 {
-    if(!tokens || !endControlHit || !atErrorCode || !savePtr)
-    {
-        return NULL;
-    }
-    char * buf = strtok_r(readData, tokens, savePtr);
-    if(!buf)
+    //AT+DRLOCK:<Address>,<EP>,<SendMode>,<Lock/Unlock>
+    //      DRLOCRSP:<nodeID>,<ep>,<status>
+    //      or
+    //      DRUNLOCKRSP:<nodeID>,<ep>,<status>
+
+    OC_LOG_V(INFO, TAG, "Enter TelSwitchDoorLockStateHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_DRLOCKUNLOCKRSP)
     {
-        return NULL;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
-    bool valid = false;
-    valid = IsThisAValidLine(buf, endControlHit, atErrorCode);
-    if(valid == true)
+
+    if (strcmp(tokens[2], AT_STR_ERROR_OK) != 0)
     {
-        return buf;
+        OC_LOG_V(INFO, TAG,
+                 "DRLOCRSP/DRUNLOCKRSP prompt contained error status %s.", tokens[4]);
+        ret = TW_RESULT_ERROR;
     }
     else
     {
-        return myStrTok(NULL, tokens, endControlHit, atErrorCode, savePtr);
+        OC_LOG_V(INFO, TAG, "DRLOCRSP/DRUNLOCKRSP prompt succeed for nodeId:%s, ep:%s.",
+                 tokens[0], tokens[1]);
+        ret = TW_RESULT_OK;
     }
+
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelSwitchDoorLockStateHandler() with ret=%d", ret);
+    return ret;
 }
 
-/**
- *
- * Reads an entire buffer, parses the buffer into individual lines, and places
- * these individual lines into the response array.
- *
- * The original command echo'd back is ignored. Any endControl items are also
- * ignored.
- *
- * If a timeout is specified greater than zero, it means you expect prompts in
- * the buffer.
- *
- * @param[out] atErrorCode The AT Error code received as Hex. 0 on success,
- *                       otherwise refer to Telegesis manual.
- * @param[out] responseArray Each individual line from read() is placed in this
-                             array.
- * @param[out] count The number of items in the response array.
- * @param[in] command The AT command that was already issued. Used to ignore
- *                    when it is echo'd back in the read buffer.
- * @param[in] timeout If not zero, it is used as a flag to determine if
- *                    blocking on read() should occur.
- *
- */
-TWResultCode ReadBuffer(uint64_t * atErrorCode,
-                        char * responseArray[],
-                        uint8_t * count,
-                        const char * command,
-                        uint8_t timeout)
+TWResultCode TelZoneEnrollRequestHandler(int count, char* tokens[])
 {
+    //ZENROLLREQ:<NodeID>,<EndPoint>,<ZoneType>,<ManufactureCode>
 
-    TWResultCode ret = TW_RESULT_OK;
-    char readData[1000] = {};
-    char itrData[200] = {};
+    OC_LOG_V(INFO, TAG, "Enter TelZoneEnrollRequestHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
 
-    ssize_t readDataBytes = 0;
-    ssize_t itrDataBytes = 0;
-    bool endControlHit = false;
-    uint8_t responseArrayPos = 0;
-    while(itrDataBytes == 0)
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_ZENROLLREQ)
     {
-        itrDataBytes += read(g_fd, itrData, sizeof(itrData)-1);
-        if(itrDataBytes < 0)
-        {
-            OC_LOG_V(ERROR, TAG, "Could not read from port. Errno is: %d", errno);
-            return TW_RESULT_ERROR;
-        }
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
+    }
 
-        if(command)
-        {
-            size_t itrDataIndexLength = (strlen(itrData) - 1);
-            if(strncmp(itrData, command, strlen(command)) == 0 &&
-               itrData[itrDataIndexLength] == '\r')
-            {
-                memset(itrData, 0, sizeof(itrData));
-                itrDataBytes = 0; // Ignore any single line which only echo'd
-                                  // the command. This allows us to block on read().
-            }
-        }
-        if(itrDataBytes > 0 &&
-           readDataBytes < (ssize_t)sizeof(readData) &&
-           (readDataBytes + itrDataBytes) <= (ssize_t)sizeof(readData))
-        {
-            readDataBytes += itrDataBytes;
-            OICStrcat(readData, sizeof(readData), itrData);
-            if(itrDataBytes == sizeof(itrData))
-            {
-reread:
-                memset(itrData, 0, sizeof(itrData));
-                itrDataBytes = 0;
-            }
-        }
+    OC_LOG_V(INFO, TAG, "Received zone request from:");
+    OC_LOG_V(INFO, TAG, "Node:%s", tokens[0]);
+    OC_LOG_V(INFO, TAG, "EP:%s", tokens[1]);
+    OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[2]);
+    OC_LOG_V(INFO, TAG, "ManufactureCode:%s", tokens[3]);
+    ret = TW_RESULT_OK;
 
-        if(timeout != 0)
-        {
-            break; // Don't block on read as there are no prompts waiting in the buffer.
-        }
-    }
-    if(readDataBytes > 0)
-    {
-        char * savePtr = NULL;
-        char * singleLine = myStrTok(readData, "\r\n", &endControlHit, atErrorCode, &savePtr);
-        while(singleLine)
-        {
-            // Stop on endControl items. Also leave function when an endControl is found.
-            //singleLine = myStrTok(NULL, "\r", &endControlHit, atErrorCode, &savePtr);
-            if(singleLine)
-            {
-                // Ignore the echo'd command line if it was passed in.
-                if(!command || (command && strcmp(singleLine, command) != 0))
-                {
-                    responseArray[responseArrayPos] = (char *) OICMalloc((strlen(singleLine)+1) *
-                                                      sizeof(char));
-                    if(!responseArray[responseArrayPos])
-                    {
-                        return TW_RESULT_ERROR_NO_MEMORY;
-                    }
-                    memset(responseArray[responseArrayPos],
-                           0,
-                           (strlen(singleLine)+1) * sizeof(char));
-                    strcpy(responseArray[responseArrayPos], singleLine);
-                    responseArrayPos++;
-                }
-                singleLine = myStrTok(NULL, "\r\n", &endControlHit, atErrorCode, &savePtr);
-            }
-        }
-        *count = responseArrayPos;
-    }
-    if(endControlHit == false && timeout == 0)
-    {
-       memset(readData, 0, sizeof(readData));
-       readDataBytes = 0;
-       goto reread;
-    }
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelZoneEnrollRequestHandler() with ret=%d", ret);
     return ret;
 }
 
-/**
- *
- * Writes AT command to buffer.
- *
- * @param[in] command The command to be written to the buffer.
- *
- */
-TWResultCode WriteBuffer(const char * command)
+TWResultCode TelEnrolledHandler(int count, char* tokens[])
 {
+    //ENROLLED:<ZID>,<ZoneType>,<EUI>
+
+    OC_LOG_V(INFO, TAG, "Enter TelEnrolledHandler()");
     TWResultCode ret = TW_RESULT_OK;
 
-    if(!command)
-    {
-        return TW_RESULT_ERROR_INVALID_PARAMS;
-    }
-    size_t sendCommandSize = (strlen(command) + 2) * sizeof(char);
-    char * sendCommand = (char *) OICMalloc(sendCommandSize);
-    if(!sendCommand)
+    if(!tokens || count != RESPONSE_PARAMS_COUNT_ENROLLED)
     {
-        return TW_RESULT_ERROR_NO_MEMORY;
-    }
-    memset(sendCommand, 0, sendCommandSize);
-    sprintf(sendCommand, "%s\r", command);
-    size_t expectedWrittenBytes = strlen(sendCommand);
-    size_t actualWrittenBytes = write(g_fd, sendCommand, expectedWrittenBytes);
-    if(actualWrittenBytes <= 0)
-    {
-        OC_LOG_V(ERROR, TAG, "Could not write to port. Errno is: %d", errno);
-        ret =  TW_RESULT_ERROR;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
         goto exit;
     }
-    if(actualWrittenBytes != expectedWrittenBytes)
+
+    OC_LOG_V(INFO, TAG, "Received zone enrollment for:");
+    OC_LOG_V(INFO, TAG, "ZID:%s", tokens[0]);
+    OC_LOG_V(INFO, TAG, "ZoneType:%s", tokens[1]);
+    OC_LOG_V(INFO, TAG, "EUI:%s", tokens[2]);
+
+    TWEnrollee enrollee;
+    OICStrcpy(enrollee.zoneId, SIZE_ZONEID, tokens[0]);
+    OICStrcpy(enrollee.zoneType, SIZE_ZONETYPE, tokens[1]);
+    OICStrcpy(enrollee.eui, SIZE_EUI, tokens[2]);
+
+    if (g_EnrollmentSucceedCallback != NULL)
     {
-        ret = TW_RESULT_ERROR;
-        goto exit;
+        OC_LOG_V(INFO, TAG, "Enrolled - Invoke callback");
+        g_EnrollmentSucceedCallback(&enrollee);
     }
+    ret = TW_RESULT_OK;
 
 exit:
-    OICFree(sendCommand);
+    OC_LOG_V(INFO, TAG, "Leave TelEnrolledHandler() with ret=%d", ret);
     return ret;
 }
 
-/**
- *
- * Deallocate items in the given arrays.
- *
- */
-void CleanArray(char* responseArray[], char* promptArray[],
-                uint8_t responseCount, uint8_t promptCount)
+TWResultCode TelZoneStatusHandler(int count, char* tokens[])
 {
-    OC_LOG_V(INFO, TAG, "Enter CleanArray().");
+    //ZONESTATUS:<NodeID>,<EP>,<ZoneStatus>,<ExtendStatus>[,<ZoneID>,<Delay>]
+    //ZONESTATUS:5FBA,01,0021,00,01,00AF
 
-    if(responseCount > ARRAY_LENGTH || promptCount > ARRAY_LENGTH)
+    OC_LOG_V(INFO, TAG, "Enter TelZoneStatusHandler()");
+    TWResultCode ret = TW_RESULT_UNKNOWN;
+    if(!tokens ||
+       ((count != RESPONSE_PARAMS_COUNT_ZONESTATUS_4) &&
+        (count != RESPONSE_PARAMS_COUNT_ZONESTATUS_6)))
     {
-        OC_LOG_V(ERROR, TAG, "Trying to access arrays out of bounds.");
-        return;
+        OC_LOG_V(ERROR, TAG, "Invalid Params");
+        ret = TW_RESULT_ERROR_INVALID_PARAMS;
+        goto exit;
     }
 
-    OC_LOG_V(INFO, TAG, "Attempt to free responseArray and promptArray.");
-    int i = 0;
-    if (responseArray)
+    TWUpdate update;
+    OICStrcpy(update.nodeId, SIZE_NODEID, tokens[0]);
+    OICStrcpy(update.endpoint, SIZE_NODEID, tokens[1]);
+    OICStrcpy(update.status, SIZE_NODEID, tokens[2]);
+    OICStrcpy(update.extendedStatus, SIZE_NODEID, tokens[3]);
+
+    if (count == RESPONSE_PARAMS_COUNT_ZONESTATUS_6)
     {
-        for (; i < responseCount; i++)
-        {
-            OC_LOG_V(INFO, TAG, "Free responseArray[%d]: %s", i, responseArray[i]);
-            OICFree(responseArray[i]);
-        }
+        OICStrcpy(update.zoneId, SIZE_NODEID, tokens[4]);
+        OICStrcpy(update.delay, SIZE_NODEID, tokens[5]);
     }
 
-    if (promptArray)
+    if (g_DeviceStatusUpdateCallback != NULL)
     {
-        i = 0;
-        for (; i < promptCount; i++)
-        {
-            OC_LOG_V(INFO, TAG, "Free promptArray[%d]: %s", i, promptArray[i]);
-            OICFree(promptArray[i]);
-        }
+        OC_LOG_V(INFO, TAG, "device status update - invoke callback");
+        g_DeviceStatusUpdateCallback(&update);
     }
+    ret = TW_RESULT_OK;
 
-    OC_LOG_V(INFO, TAG, "Leave CleanArray().");
+exit:
+    OC_LOG_V(INFO, TAG, "Leave TelZoneStatusHandler() with ret=%d", ret);
+    return ret;
 }
 
+//-----------------------------------------------------------------------------
+// Internal functions - Helpers
+//-----------------------------------------------------------------------------
+
 /**
  *
- * Print the given arrays.
+ * Tokenize 'input' parameter by 'delimiters' into 'output' array.
  *
  */
-void PrintArray(char* responseArray[], char* promptArray[],
-                uint8_t responseCount, uint8_t promptCount)
+int Tokenize(const char *input, const char* delimiters, char* output[])
 {
-    OC_LOG_V(INFO, TAG, "Enter PrintArray().");
+    OC_LOG_V(INFO, TAG, "Enter Tokenize() - %s", input);
 
-    if(responseCount > ARRAY_LENGTH || promptCount > ARRAY_LENGTH)
+    if (output == NULL)
     {
-        OC_LOG_V(ERROR, TAG, "Trying to access arrays out of bounds.");
-        return;
+        OC_LOG_V(INFO, TAG, "Invalid parameter.");
+        return -1;
     }
 
-    int n = 0;
-    OC_LOG_V(INFO, TAG, "responseCount=%d", responseCount);
-    for (; n < responseCount; n++)
-    {
-        OC_LOG_V(INFO, TAG, "responseArray[%d]=%s", n, responseArray[n]);
-    }
+    int length = strlen(input);
+    char * str = (char *) OICCalloc(1, length + 1);
+    OICStrcpy(str, length+1, input);
 
-    OC_LOG_V(INFO, TAG, "promptCount=%d", promptCount);
-    for (n = 0; n < promptCount; n++)
+    char* savePtr = NULL;
+    char* p   = strtok_r(str, delimiters, &savePtr);
+    int index = 0;
+    while (p && index <= ARRAY_LENGTH)
     {
-        OC_LOG_V(INFO, TAG, "promptArray[%d]=%s", n, promptArray[n]);
+        int size = strlen(p) + 1;   //for null char
+        output[index] = (char*)OICCalloc(size, sizeof(char));
+        OICStrcpy(output[index], size, p);
+        OC_LOG_V(INFO, TAG, "Token[%d]=%s", index, output[index]);
+        p = strtok_r (NULL, delimiters, &savePtr);
+        index++;
     }
 
-    OC_LOG_V(INFO, TAG, "Leave PrintArray().");
+    OICFree(str);
+    OC_LOG_V(INFO, TAG, "Leave Tokenize()");
+    return index;
 }
 
-
-/**
- *
- * Print the given device.
- *
- */
-void PrintTWDevice(TWDevice* device)
+int AsciiToHex(char c)
 {
-    if (device != NULL)
+    int num = (int) c;
+    if(c >= '0' && c <= '9')
     {
-        OC_LOG_V(INFO, TAG, "Device - NodeID=%s", device->nodeId);
-        OC_LOG_V(INFO, TAG, "Device - EPID=%s", device->endpointOfInterest->endpointId);
+        return num - '0';
     }
-    else
+
+    if(num >= 'A' && num <= 'F')
     {
-        OC_LOG_V(ERROR, TAG, "Received a NULL device - CAN'T PRINT IT.");
+        return num - 'A' + 10;
     }
+    return -1;
 }
 
-/**
- *
- * Print the given device list.
- *
- */
-void PrintTWDeviceList(TWDeviceList* list)
+TWResultCode AsciiHexToValue(char* hexString, int length, uint64_t* value)
 {
-    int i = 0;
-    for (; i < list->count; i++)
+    if(!hexString || !value || length < 0)
+    {
+        return TW_RESULT_ERROR_INVALID_PARAMS;
+    }
+    int retVal = AsciiToHex(hexString[0]);
+    if(retVal == -1)
+    {
+        OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
+        return TW_RESULT_ERROR;
+    }
+    *value = (uint64_t)retVal;
+    for (int i = 1; i < length; ++i)
     {
-        PrintTWDevice(&list->deviceList[i]);
+        if (sizeof(hexString) > (uint32_t)i)
+        {
+            *value <<= 4;
+            retVal = AsciiToHex(hexString[i]);
+            if(retVal == -1)
+            {
+                OC_LOG(ERROR, TAG, "Bad conversion from ASCII To Hex.");
+                return TW_RESULT_ERROR;
+            }
+            *value |= (uint64_t)retVal;
+        }
     }
+    return TW_RESULT_OK;
 }
 
 /**
@@ -2730,7 +2765,6 @@ void DeallocateTWDeviceList()
     OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList);
     g_FoundMatchedDeviceList->deviceList->endpointOfInterest->clusterList = NULL;
 
-
     OICFree(g_FoundMatchedDeviceList->deviceList->endpointOfInterest);
     g_FoundMatchedDeviceList->deviceList->endpointOfInterest = NULL;