Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / csdk / stack / src / oicgroup.c
index b9f70ac..47d34be 100644 (file)
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 #define _POSIX_C_SOURCE 200112L
+
 #include <string.h>
 
+#include "oicgroup.h"
 #include "cJSON.h"
 #include "ocmalloc.h"
-#include "oicgroup.h"
-#include "ocresource.h"
 #include "occollection.h"
+#include "logger.h"
+#include "timer.h"
+
+#ifndef WITH_ARDUINO
+#include <pthread.h>
+#endif
 
 #define TAG PCF("OICGROUP")
 
-#define DESC_DELIMITER "\""
-#define ACTION_DELIMITER "*"
-#define ATTR_DELIMITER "|"
+#define DESC_DELIMITER          "\""
+#define ACTION_DELIMITER        "*"
+#define ATTR_DELIMITER          "|"
+#define ATTR_ASSIGN             "="
+
+// Definitions for operations related to actions
+#define DO_ACTION               "DoAction"
+#define GET_ACTIONSET           "GetActionSet"
+#define ACTIONSET               "ActionSet"
+#define DELETE_ACTIONSET        "DelActionSet"
+
+#define OIC_ACTION_PREFIX               "{\"oc\":[{\"rep\":{"
+#define VARIFY_POINTER_NULL(pointer, result, toExit) \
+    if(pointer == NULL) \
+    {\
+        result = OC_STACK_NO_MEMORY;\
+        goto toExit;\
+    }
+#define VARIFY_PARAM_NULL(pointer, result, toExit) \
+    if(pointer == NULL)\
+    {\
+        result = OC_STACK_INVALID_PARAM;\
+        goto exit;\
+    }
+
+#define OCFREE(pointer) \
+    { \
+        OCFree(pointer); \
+        pointer = NULL; \
+    }
+
+#ifndef WITH_ARDUINO
+pthread_mutex_t lock;
+#endif
+
+enum ACTION_TYPE
+{
+    NONE = 0, SCHEDULED, RECURSIVE
+};
+
+typedef struct scheduledresourceinfo
+{
+    OCResource *resource;
+    OCActionSet *actionset;
+
+    int timer_id;
+
+    OCServerRequest *ehRequest;
+
+    time_t time;
+    struct scheduledresourceinfo* next;
+} ScheduledResourceInfo;
+
+ScheduledResourceInfo *scheduleResourceList = NULL;
+
+void AddScheduledResource(ScheduledResourceInfo **head,
+        ScheduledResourceInfo* add)
+{
+    OC_LOG(INFO, TAG, PCF("AddScheduledResource Entering..."));
+
+#ifndef WITH_ARDUINO
+    pthread_mutex_lock(&lock);
+#endif
+    ScheduledResourceInfo *tmp = NULL;
+
+    if (*head != NULL)
+    {
+        tmp = *head;
+
+        while (tmp->next)
+        {
+            tmp = tmp->next;
+        }
+        tmp->next = add;
+    }
+    else
+    {
+        *head = add;
+    }
+#ifndef WITH_ARDUINO
+    pthread_mutex_unlock(&lock);
+#endif
+}
+
+ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
+{
+    OC_LOG(INFO, TAG, PCF("GetScheduledResource Entering..."));
+
+#ifndef WITH_ARDUINO
+    pthread_mutex_lock(&lock);
+#endif
+
+    time_t t_now;
+
+    ScheduledResourceInfo *tmp = NULL;
+    tmp = head;
+
+#ifndef WITH_ARDUINO
+    time(&t_now);
+#else
+    t_now = now();
+#endif
+
+    if (tmp)
+    {
+        while (tmp)
+        {
+            time_t diffTm = 0;
+#ifndef WITH_ARDUINO
+            diffTm = timespec_diff(tmp->time, t_now);
+#else
+            diffTm = timespec_diff(tmp->time, t_now);
+#endif
+
+            if (diffTm <= (time_t) 0)
+            {
+                OC_LOG(INFO, TAG, PCF("return Call INFO."));
+                goto exit;
+            }
+
+            tmp = tmp->next;
+        }
+    }
+
+    exit:
+#ifndef WITH_ARDUINO
+    pthread_mutex_unlock(&lock);
+#endif
+    if (tmp == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
+    }
+    return tmp;
+}
+
+ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
+{
+    OC_LOG(INFO, TAG, PCF("GetScheduledResourceByActionSetName Entering..."));
+
+#ifndef WITH_ARDUINO
+    pthread_mutex_lock(&lock);
+#endif
+    ScheduledResourceInfo *tmp = NULL;
+    tmp = head;
+
+    if (tmp)
+    {
+        while (tmp)
+        {
+            if (strcmp(tmp->actionset->actionsetName, setName) == 0)
+            {
+                OC_LOG(INFO, TAG, PCF("return Call INFO."));
+                goto exit;
+            }
+            tmp = tmp->next;
+        }
+    }
+
+exit:
+#ifndef WITH_ARDUINO
+    pthread_mutex_unlock(&lock);
+#endif
+    if (tmp == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Cannot Find Call Info."));
+    }
+    return tmp;
+}
+
+void RemoveScheduledResource(ScheduledResourceInfo **head,
+        ScheduledResourceInfo* del)
+{
+#ifndef WITH_ARDUINO
+    pthread_mutex_lock(&lock);
+#endif
+    OC_LOG(INFO, TAG, PCF("RemoveScheduledResource Entering..."));
+    ScheduledResourceInfo *tmp = NULL;
+
+    if (del == NULL)
+    {
+        return;
+    }
+
+    if (*head == del)
+    {
+        *head = (*head)->next;
+    }
+    else
+    {
+        tmp = *head;
+        while (tmp->next && (tmp->next != del))
+        {
+            tmp = tmp->next;
+        }
+        if (tmp->next)
+        {
+            tmp->next = del->next;
+        }
+    }
+
+    OCFREE(del)
+#ifndef WITH_ARDUINO
+    pthread_mutex_unlock(&lock);
+#endif
+}
 
 typedef struct aggregatehandleinfo
 {
@@ -40,16 +248,13 @@ typedef struct aggregatehandleinfo
     OCResource *collResource;
 
     struct aggregatehandleinfo *next;
-} ClientRequstInfo;
-
-// unsigned int nHandleIdx = 0;
-// ClientRequstInfo g_AggregateResponseHandle[10];
+} ClientRequestInfo;
 
-ClientRequstInfo *clientRequstList = NULL;
+ClientRequestInfo *clientRequstList = NULL;
 
-void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add)
+void AddClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* add)
 {
-    ClientRequstInfo *tmp = NULL;
+    ClientRequestInfo *tmp = NULL;
 
     if (*head != NULL)
     {
@@ -67,9 +272,10 @@ void AddClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* add)
     }
 }
 
-ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle)
+ClientRequestInfo* GetClientRequestInfo(ClientRequestInfo *head,
+        OCDoHandle handle)
 {
-    ClientRequstInfo *tmp = NULL;
+    ClientRequestInfo *tmp = NULL;
 
     tmp = head;
 
@@ -77,7 +283,6 @@ ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle
     {
         while (tmp)
         {
-//            printf("%p :: %p\n", tmp->required, handle);
             if (tmp->required == handle)
             {
                 break;
@@ -91,9 +296,12 @@ ClientRequstInfo* GetClientRequestInfo(ClientRequstInfo *head, OCDoHandle handle
     return NULL;
 }
 
-void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del)
+void RemoveClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* del)
 {
-    ClientRequstInfo *tmp = NULL;
+    ClientRequestInfo *tmp = NULL;
+
+    if (del == NULL)
+        return;
 
     if (*head == del)
     {
@@ -113,8 +321,6 @@ void RemoveClientRequestInfo(ClientRequstInfo **head, ClientRequstInfo* del)
     }
 }
 
-
-
 void AddCapability(OCCapability** head, OCCapability* node)
 {
     OCCapability *pointer = *head;
@@ -152,31 +358,46 @@ void AddAction(OCAction** head, OCAction* node)
     }
 }
 
-void AddActionSet(OCActionSet **head, OCActionSet* node)
+OCStackResult AddActionSet(OCActionSet **head, OCActionSet* node)
 {
     OCActionSet *pointer = *head;
+    OCActionSet *prev = NULL;
+    if(node == NULL)
+    {
+        return OC_STACK_ERROR;
+    }
     if (NULL == pointer)
     {
         *head = node;
     }
     else
     {
-
-        while (pointer->next != NULL)
+        prev = pointer;
+        while (pointer != NULL)
         {
+            // check the uniqeness of actionsetname.
+            if (strcmp(pointer->actionsetName, node->actionsetName) == 0)
+            {
+                return OC_STACK_ERROR;
+            }
+
+            prev = pointer;
             pointer = pointer->next;
         }
 
-        pointer->next = node;
+        prev->next = node;
     }
+
+    return OC_STACK_OK;
 }
 
 void DeleteCapability(OCCapability *del)
 {
-    free(del->capability);
+    OCFREE(del->capability)
     del->capability = NULL;
-    free(del->status);
+    OCFREE(del->status)
     del->status = NULL;
+    OCFREE(del)
 }
 
 void DeleteAction(OCAction** action)
@@ -190,15 +411,17 @@ void DeleteAction(OCAction** action)
         pointer = pointer->next;
 
         DeleteCapability(pDel);
-        pDel->next = NULL;
     }
-    OCFree((*action)->resourceUri);
-    (*action)->resourceUri = NULL;
+    OCFREE((*action)->resourceUri)
     (*action)->next = NULL;
+    OCFREE(*action)
 }
 
 void DeleteActionSet(OCActionSet** actionset)
 {
+    if(*actionset == NULL)
+        return;
+
     OCAction* pointer = (*actionset)->head;
     OCAction* pDel = NULL;
 
@@ -208,19 +431,17 @@ void DeleteActionSet(OCActionSet** actionset)
         pointer = pointer->next;
 
         DeleteAction(&pDel);
-        pDel->next = NULL;
     }
-
-    OCFree((*actionset)->actionsetName);
-    (*actionset)->head = NULL;
+    //    (*actionset)->head = NULL;
+    OCFREE((*actionset)->actionsetName)
+    OCFREE(*actionset)
 }
 
-OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName)
+OCStackResult FindAndDeleteActionSet(OCResource **resource,
+        const char * actionsetName)
 {
-
     if (*resource != NULL)
     {
-
         OCActionSet *pointer = NULL;
         OCActionSet *pDel = NULL;
 
@@ -240,7 +461,6 @@ OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actions
                     (*resource)->actionsetHead = NULL;
 
                 DeleteActionSet(&pointer);
-
             }
             else if (pointer->next != NULL)
             {
@@ -248,7 +468,8 @@ OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actions
                 {
                     if (pointer->next != NULL)
                     {
-                        if (strcmp(pointer->next->actionsetName, actionsetName) == 0)
+                        if (strcmp(pointer->next->actionsetName, actionsetName)
+                                == 0)
                         {
                             pDel = pointer->next;
                             pointer->next = pointer->next->next;
@@ -256,6 +477,7 @@ OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actions
                             DeleteActionSet(&pDel);
                         }
                     }
+                    pointer = pointer->next;
                 }
             }
 
@@ -263,7 +485,6 @@ OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actions
         }
 
     }
-
     return OC_STACK_ERROR;
 }
 
@@ -285,7 +506,8 @@ OCStackResult DeleteActionSets(OCResource** resource)
     return OC_STACK_OK;
 }
 
-OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset)
+OCStackResult GetActionSet(const char *actionName, OCActionSet *head,
+        OCActionSet** actionset)
 {
     OCActionSet *pointer = head;
 
@@ -304,227 +526,226 @@ OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSe
 
 }
 
-OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method,
-        char **actionsetName)
+OCStackResult ExtractKeyValueFromRequest(char *request, char **key,
+        char **value)
 {
-    char *acitonRequest;
-    char *iterTokenPtr = NULL;
-    char *iterToken = NULL;
-    char *description = NULL;
-    char *iterDescPtr = NULL;
+    OCStackResult result = OC_STACK_OK;
+    size_t length = 0;
+
+    char* pRequest = (char *) request + strlen(OIC_ACTION_PREFIX);
+    char* iterToken, *iterTokenPtr;
+
+    iterToken = (char *) strtok_r(pRequest, ":", &iterTokenPtr);
+    VARIFY_POINTER_NULL(iterToken, result, exit);
+    length = strlen(iterToken) + 1;
 
-    char *attributes = NULL;
-    char *iterAttrbutesPtr = NULL;
+    *key = (char *) OCMalloc(length);
+    VARIFY_POINTER_NULL(*key, result, exit)
 
-    char *attr = NULL;
-    char *iterAttrPtr = NULL;
+    strncpy(*key, iterToken + 1, length);
+    ((*key)[((length - 1) - 2)]) = '\0';
 
-    OCActionSet* actionset = NULL;
-    OCAction* action = NULL;
+    iterToken = (char *) strtok_r(NULL, "}", &iterTokenPtr);
+    VARIFY_POINTER_NULL(iterToken, result, exit);
+    length = strlen(iterToken) + 1;
 
-    acitonRequest = (char *) OCMalloc(strlen((char *) request) + 1);
-    strncpy(acitonRequest, (char *) request, strlen((char *) request) + 1);
+    *value = (char *) OCMalloc(length);
+    VARIFY_POINTER_NULL(*value, result, exit)
 
-    //printf("\t%s\n", acitonRequest);
-    if (acitonRequest != NULL)
+    strncpy(*value, iterToken + 1, length);
+    ((*value)[((length - 1) - 2)]) = '\0';
+
+exit:
+    if (result != OC_STACK_OK)
     {
-        iterToken = (char *) strtok_r(acitonRequest, DESC_DELIMITER, &iterTokenPtr);
+        OCFREE(*key)
+        OCFREE(*value)
+    }
 
-        while (iterToken != NULL)
-        {
-            if (strcmp(iterToken, "ActionSet") == 0)
-            { // if iterToken is ActionSet, will be created and added a new action set.
-
-                *method = (char *) OCMalloc(strlen(iterToken) + 1);
-                strncpy(*method, iterToken, strlen(iterToken) + 1);
-
-                //GetActionName(iterToken, &actionsetName);
-                // printf("%s\n", iterToken, &iterTokenPtr);
-                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
-                // printf("%s\n", iterToken);
-                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
-                // printf("%s\n", iterToken);
-
-                // printf("DESC :: %s\n", iterToken);
-                description = (char *) OCMalloc(strlen(iterToken) + 1);
-                strncpy(description, iterToken, strlen(iterToken) + 1);
-                // printf("DESC Copied :: %s\n", description);
-
-                // Find the action name from description.
-                iterDescPtr = NULL;
-                iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
-                //while(iterToken != NULL)
-                if (iterToken != NULL)
-                {
-                    if (*actionsetName != NULL)
-                    {
-                        // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
-                        return OC_STACK_ERROR; // ERROR OCCURED.
-                    }
-                    else
-                    {
-                        //  Actionset name.
-                        // printf("ACTION SET NAME :: %s\n", iterToken);
-                        *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
+    return result;
+}
 
-                        strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
-                        // printf("ACTION SET NAME :: %s\n", *actionsetName);
-                        // break;
-                    }
+OCStackResult ExtractActionSetNameAndDelaytime(char *pChar, char **setName,
+        long int *pa)
+{
+    char *token, *tokenPtr;
+    OCStackResult result = OC_STACK_OK;
 
-                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
-                }
-                else
-                {
-                    return OC_STACK_ERROR;
+    token = (char*) strtok_r(pChar, ACTION_DELIMITER, &tokenPtr);
+    *setName = (char *) OCMalloc(strlen(token) + 1);
+    VARIFY_POINTER_NULL(*setName, result, exit)
+    VARIFY_PARAM_NULL(token, result, exit)
+    strncpy(*setName, token, strlen(token) + 1);
 
-                } // end Action Set Name.
+    token = strtok_r(NULL, ACTION_DELIMITER, &tokenPtr);
+    VARIFY_POINTER_NULL(pa, result, exit)
+    VARIFY_PARAM_NULL(token, result, exit)
+    *pa = atoi(token);
 
-                // New ActionSet Add to OCResource's ActionSet list.
-                // 1. Allocate a new pointer for actionset.
-                actionset = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
-                // 2. Initiate actionset.
-                memset(actionset, 0, sizeof(OCActionSet));
-                actionset->actionsetName = (char *) OCMalloc(strlen(*actionsetName) + 1);
-                strncpy(actionset->actionsetName, *actionsetName, strlen(*actionsetName) + 1);
-                // printf("ACTION SET NAME :: %s\n", actionset->actionsetName);
+    return OC_STACK_OK;
 
-                while (iterToken != NULL)
-                {
-                    action = (OCAction *) OCMalloc(sizeof(OCAction));
-                    memset(action, 0, sizeof(OCAction));
+exit:
+    OCFREE(*setName);
+    return result;
+}
 
-                    // printf("ATTR Copied :: %s\n", iterToken);
-                    attributes = (char *) OCMalloc(strlen(iterToken) + 1);
-                    strncpy(attributes, iterToken, strlen(iterToken) + 1);
-                    // printf("ATTR Copied :: %s\n", attributes);
+OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
+{
+    OCStackResult result = OC_STACK_OK;
 
-                    iterToken = (char *) strtok_r(attributes, ATTR_DELIMITER, &iterAttrbutesPtr);
-                    while (iterToken != NULL)
-                    {
-                        attr = (char *) OCMalloc(strlen(iterToken) + 1);
-                        strncpy(attr, iterToken, strlen(iterToken) + 1);
+    char *iterToken = NULL, *iterTokenPtr = NULL;
+    char *descIterToken = NULL, *descIterTokenPtr = NULL;
+    char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
+    char *desc = NULL, *attr = NULL;
+    char *key = NULL, *value = NULL;
 
-                        iterToken = (char *) strtok_r(attr, "=", &iterAttrPtr);
-                        while (iterToken != NULL)
-                        {
-                            // Find the URI from description.
-                            if (strcmp(iterToken, "uri") == 0)
-                            {
-                                iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
-                                //printf("uri :: %s\n", iterToken);
-                                action->resourceUri = (char *) OCMalloc(strlen(iterToken) + 1);
-                                strncpy(action->resourceUri, iterToken, strlen(iterToken) + 1);
-                            }
-                            else
-                            {
-                                OCCapability* capa = (OCCapability*) OCMalloc(sizeof(OCCapability));
-                                memset(capa, 0, sizeof(OCCapability));
-                                //printf("%s :: ", iterToken);
-                                capa->capability = (char *) OCMalloc(strlen(iterToken) + 1);
-                                strncpy(capa->capability, iterToken, strlen(iterToken) + 1);
-                                iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
-                                //printf("%s\n", iterToken);
-                                capa->status = (char *) OCMalloc(strlen(iterToken) + 1);
-                                strncpy(capa->status, iterToken, strlen(iterToken) + 1);
-
-                                AddCapability(&action->head, capa);
-                            }
+    OCAction *action = NULL;
+    OCCapability *capa = NULL;
 
-                            iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
-                        }
+    OC_LOG(INFO, TAG, PCF("Build ActionSet Instance."));
 
-                        iterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &iterAttrbutesPtr);
-                    } // End of Action
+    *set = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
+    VARIFY_POINTER_NULL(*set, result, exit)
 
-                    AddAction(&actionset->head, action);
+    iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
 
-                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
-                }
+    // ActionSet Name
+    memset(*set, 0, sizeof(OCActionSet));
+    (*set)->actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
+    VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
+    VARIFY_PARAM_NULL(iterToken, result, exit)
+    strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
+
+    // Time info. for Scheduled/Recursive Group action.
+    // d is meant Day of the week.
+    // T is meant ActionType.
+    // yyyy-mm-dd hh:mm:ss d
+    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
+    VARIFY_PARAM_NULL(iterToken, result, exit)
+#ifndef WITH_ARDUINO
+    sscanf(iterToken, "%ld %d", &(*set)->timesteps, &(*set)->type);
+#endif
 
-                // 3. Add the pointer OCResource's ActionSet list.
-                AddActionSet(&(*resource)->actionsetHead, actionset);
-                return OC_STACK_OK;
+    OC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
+
+    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
+    while (iterToken)
+    {
+        desc = (char *) OCMalloc(strlen(iterToken) + 1);
+        VARIFY_POINTER_NULL(desc, result, exit)
+        VARIFY_PARAM_NULL(desc, result, exit)
+        strncpy(desc, iterToken, strlen(iterToken) + 1);
+        descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER,
+                &descIterTokenPtr);
+        while (descIterToken)
+        {
+            attr = (char *) OCMalloc(strlen(descIterToken) + 1);
+            VARIFY_POINTER_NULL(attr, result, exit)
+            VARIFY_PARAM_NULL(descIterToken, result, exit)
+            strncpy(attr, descIterToken, strlen(descIterToken) + 1);
+
+            attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN,
+                    &attrIterTokenPtr);
+            key = (char *) OCMalloc(strlen(attrIterToken) + 1);
+            VARIFY_POINTER_NULL(key, result, exit)
+            VARIFY_PARAM_NULL(attrIterToken, result, exit)
+            strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
+
+            attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN,
+                    &attrIterTokenPtr);
+            value = (char *) OCMalloc(strlen(attrIterToken) + 1);
+            VARIFY_POINTER_NULL(value, result, exit)
+            VARIFY_PARAM_NULL(attrIterToken, result, exit)
+            strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
+
+            if (strcmp(key, "uri") == 0)
+            {
+                OC_LOG(INFO, TAG, PCF("Build OCAction Instance."));
+
+                action = (OCAction*) OCMalloc(sizeof(OCAction));
+                VARIFY_POINTER_NULL(action, result, exit)
+                memset(action, 0, sizeof(OCAction));
+                action->resourceUri = (char *) OCMalloc(strlen(value) + 1);
+                VARIFY_POINTER_NULL(action->resourceUri, result, exit)
+                VARIFY_PARAM_NULL(value, result, exit)
+                strncpy(action->resourceUri, value, strlen(value) + 1);
             }
-            else if (strcmp(iterToken, "DoAction") == 0 || strcmp(iterToken, "DelActionSet") == 0
-                    || strcmp(iterToken, "GetActionSet") == 0)
+            else
             {
-                *method = (char *) OCMalloc(strlen(iterToken) + 1);
-                strncpy(*method, iterToken, strlen(iterToken) + 1);
+                if ((key != NULL) && (value != NULL))
+                {
+                    OC_LOG(INFO, TAG, PCF("Build OCCapability Instance."));
 
-                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
-                // printf("%s\n", iterToken);
-                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
-                // printf("%s\n", iterToken);
+                    capa = (OCCapability*) OCMalloc(sizeof(OCCapability));
+                    VARIFY_POINTER_NULL(capa, result, exit)
+                    memset(capa, 0, sizeof(OCCapability));
 
-                description = (char *) OCMalloc(strlen(iterToken) + 1);
-                strncpy(description, iterToken, strlen(iterToken) + 1);
+                    capa->capability = (char *) OCMalloc(strlen(key) + 1);
+                    VARIFY_POINTER_NULL(capa->capability, result, exit)
+                    VARIFY_PARAM_NULL(key, result, exit)
+                    strncpy(capa->capability, key, strlen(key) + 1);
 
-                // Find the action name from description.
-                iterDescPtr = NULL;
-                iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
-                if (iterToken != NULL)
-                {
-                    if (*actionsetName != NULL)
-                    {
-                        // printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
-                        return OC_STACK_ERROR; // ERROR OCCURED.
-                    }
-                    else
-                    {
-                        //  Actionset name.
-                        // printf("ACTION SET NAME :: %s\n", iterToken);
-                        *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
+                    capa->status = (char *) OCMalloc(strlen(value) + 1);
+                    VARIFY_POINTER_NULL(capa->status, result, exit)
+                    VARIFY_PARAM_NULL(value, result, exit)
+                    strncpy(capa->status, value, strlen(value) + 1);
 
-                        strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
-                        // printf("ACTION SET NAME :: %s\n", *actionsetName);
-                    }
+                    VARIFY_POINTER_NULL(action, result, exit)
 
-                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
-                    return OC_STACK_OK;
+                    AddCapability(&action->head, capa);
                 }
-                else
-                {
-                    return OC_STACK_ERROR;
-
-                } // end Action Set Name.
-                break;
             }
 
-            iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);
+            OCFREE(key)
+            OCFREE(value)
+            OCFREE(attr)
+
+            descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER,
+                    &descIterTokenPtr);
         }
+
+        AddAction(&(*set)->head, action);
+        iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
+        OCFREE(desc);
     }
 
-    return OC_STACK_ERROR;
+    return OC_STACK_OK;
+exit:
+    OCFREE(attr)
+    OCFREE(desc)
+    OCFREE(capa)
+    OCFREE(action)
+    OCFREE(*set)
+    OCFREE(key)
+    OCFREE(value)
+    OCFREE(attr)
+
+    return result;
 }
 
-OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc)
+OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
 {
-    char temp[1024] =
-    { 0 };
+    char temp[1024] = { 0 };
     int remaining = 1023;
+    OCStackResult res = OC_STACK_ERROR;
 
-    // OCActionSet *as = resource->actionsetHead;
-    // while(as != NULL)
-    // {
-    printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName);
     OCAction *action = actionset->head;
 
     if (remaining >= strlen(actionset->actionsetName) + 1)
     {
         strcat(temp, actionset->actionsetName);
         remaining -= strlen(actionset->actionsetName);
-        strcat(temp, "*");
+        strcat(temp, ACTION_DELIMITER);
         remaining--;
     }
     else
     {
-        return OC_STACK_ERROR;
+        res = OC_STACK_ERROR;
+        goto exit;
     }
 
     while (action != NULL)
     {
-        printf("\tURI :: %s\n", action->resourceUri);
         strcat(temp, "uri=");
         remaining -= strlen("uri=");
         strcat(temp, action->resourceUri);
@@ -535,7 +756,6 @@ OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc)
         OCCapability *capas = action->head;
         while (capas != NULL)
         {
-            printf("\t\t%s = %s\n", capas->capability, capas->status);
             strcat(temp, capas->capability);
             remaining -= strlen(capas->capability);
             strcat(temp, "=");
@@ -553,26 +773,29 @@ OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc)
         action = action->next;
         if (action != NULL)
         {
-            strcat(temp, "*");
+            strcat(temp, ACTION_DELIMITER);
             remaining--;
         }
     }
-    //     as = as->next;
-    // }
 
     *desc = (char *) OCMalloc(1024 - remaining);
+    VARIFY_POINTER_NULL(*desc, res, exit);
     strcpy(*desc, temp);
-    // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining);
 
     return OC_STACK_OK;
+
+exit:
+    OCFREE(*desc);
+    return res;
+
 }
 
 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
         OCClientResponse* clientResponse)
 {
-    printf("\n\n\tcallback is called\n\n");
+    OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
 
-    ClientRequstInfo *info = GetClientRequestInfo(clientRequstList, handle);
+    ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
 
     if (info)
     {
@@ -580,19 +803,23 @@ OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
 
         unsigned char *responseJson;
         responseJson = (unsigned char *) OCMalloc(
-                (unsigned int) (strlen((char *) clientResponse->resJSONPayload) + 1));
+                (unsigned int) (strlen((char *) clientResponse->resJSONPayload)
+                        + 1));
+
+        if( responseJson == NULL )
+            return OC_STACK_DELETE_TRANSACTION;
 
         // We need the body of response.
         // Copy the body from the response
-        strcpy((char *) responseJson, ((char *) clientResponse->resJSONPayload
-                + OC_JSON_PREFIX_LEN));
+        strcpy((char *) responseJson,
+                ((char *) clientResponse->resJSONPayload + OC_JSON_PREFIX_LEN));
         idx = strlen((char *) responseJson) - OC_JSON_SUFFIX_LEN;
         // And insert NULL at the end of body.
         (responseJson[idx]) = 0;
 
         OCEntityHandlerResponse response = { 0 };
         response.ehResult = OC_EH_OK;
-        response.payload = responseJson;
+        response.payload = (char*)responseJson;
         response.payloadSize = (unsigned int) strlen((char *) responseJson) + 1;
         response.persistentBufferFlag = 0;
         response.requestHandle = (OCRequestHandle) info->ehRequest;
@@ -601,22 +828,19 @@ OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
         OCDoResponse(&response);
 
         RemoveClientRequestInfo(&clientRequstList, info);
-        OCFree(responseJson);
+        OCFREE(info)
+        OCFREE(responseJson)
     }
 
-    // g_AggregateResponseHandle
-
     return OC_STACK_KEEP_TRANSACTION;
 }
 
 void ActionSetCD(void *context)
 {
-    // printf("\n\t\tCD is called\n");
-
-    // free( context );
 }
 
-OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining)
+OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr,
+        uint16_t *remaining)
 {
     OCStackResult ret = OC_STACK_ERROR;
     cJSON *json;
@@ -633,7 +857,8 @@ OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16
     OCCapability* pointerCapa = action->head;
     while (pointerCapa)
     {
-        cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status);
+        cJSON_AddStringToObject(body, pointerCapa->capability,
+                pointerCapa->status);
         pointerCapa = pointerCapa->next;
     }
 
@@ -656,47 +881,169 @@ OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16
 
 unsigned int GetNumOfTargetResource(OCAction *actionset)
 {
-    int numOfREsource = 0;
+    int numOfResource = 0;
 
     OCAction *pointerAction = actionset;
 
     while (pointerAction != NULL)
     {
-        numOfREsource++;
+        numOfResource++;
         pointerAction = pointerAction->next;
     }
 
-    return numOfREsource;
+    return numOfResource;
 }
 
-OCStackResult SendAction(OCDoHandle *handle, const char *targetUri, const unsigned char *action)
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+OCStackResult SendAction(OCDoHandle *handle, const char *targetUri,
+        const unsigned char *action)
 {
-    OCCallbackData cbdata =
-    { 0 };
+    OCCallbackData cbdata = { 0 };
     cbdata.cb = &ActionSetCB;
-    cbdata.cd = &ActionSetCD;
-    cbdata.context = (void *) 0x99;
+    cbdata.cd = NULL;
+    cbdata.context = (void*)DEFAULT_CONTEXT_VALUE;
+
+// TODO: Selecting OC_IPV4.
+// It is temporary change as OC_ALL is not working currently. Remove this code and use OC_ALL
+// once it is functioning.
 
     return OCDoResource(handle, OC_REST_PUT, targetUri,
-    //temp->rsrcType->resourcetypename,
-            NULL, (char *) action, OC_NA_QOS, &cbdata, NULL, 0);
+    NULL, (char *) action, OC_IPV4, OC_NA_QOS, &cbdata, NULL, 0);
+}
+
+OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
+        OCServerRequest* requestHandle)
+{
+    OCStackResult result = OC_STACK_ERROR;
+    OCAction *pointerAction = actionset->head;
+
+    while (pointerAction != NULL)
+    {
+        unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
+        unsigned char* actionDescPtr = actionDesc;
+        uint16_t remaining = MAX_RESPONSE_LENGTH;
+
+        strncpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX,
+                strlen((const char *) OC_JSON_PREFIX) + 1);
+        BuildActionJSON(pointerAction, actionDescPtr, &remaining);
+        strncat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX,
+                strlen((const char *) OC_JSON_SUFFIX));
+
+        ClientRequestInfo *info = (ClientRequestInfo *) OCMalloc(
+                sizeof(ClientRequestInfo));
+
+        if( info == NULL )
+            return OC_STACK_NO_MEMORY;
+
+        memset(info, 0, sizeof(ClientRequestInfo));
+
+        info->collResource = resource;
+        info->ehRequest = requestHandle;
+
+        result = SendAction(&info->required, pointerAction->resourceUri,
+                actionDescPtr);
+        if (result != OC_STACK_OK)
+        {
+            return result;
+        }
+
+        AddClientRequestInfo(&clientRequstList, info);
+
+        pointerAction = pointerAction->next;
+    }
+
+    return result;
 }
 
-OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
-        OCResource *resource, OCEntityHandlerRequest *ehRequest)
+void DoScheduledGroupAction()
+{
+    OC_LOG(INFO, TAG, PCF("DoScheduledGroupAction Entering..."));
+    ScheduledResourceInfo* info = GetScheduledResource(scheduleResourceList);
+
+    if (info == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
+        goto exit;
+    }
+    else if (info->resource == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Target resource is NULL"));
+        goto exit;
+    }
+    else if (info->actionset == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
+        goto exit;
+    }
+    else if (info->ehRequest == NULL)
+    {
+        OC_LOG(INFO, TAG, PCF("Target ActionSet is NULL"));
+        goto exit;
+    }
+#ifndef WITH_ARDUINO
+    pthread_mutex_lock(&lock);
+#endif
+    DoAction(info->resource, info->actionset, info->ehRequest);
+#ifndef WITH_ARDUINO
+    pthread_mutex_unlock(&lock);
+#endif
+
+    if (info->actionset->type == RECURSIVE)
+    {
+        ScheduledResourceInfo *schedule;
+        schedule = (ScheduledResourceInfo *) OCMalloc(
+                sizeof(ScheduledResourceInfo));
+
+        if (schedule)
+        {
+            OC_LOG(INFO, TAG, PCF("Building New Call Info."));
+            memset(schedule, 0, sizeof(ScheduledResourceInfo));
+
+            if (info->actionset->timesteps > 0)
+            {
+#ifndef WITH_ARDUINO
+                pthread_mutex_lock(&lock);
+#endif
+                schedule->resource = info->resource;
+                schedule->actionset = info->actionset;
+                schedule->ehRequest = info->ehRequest;
+
+                schedule->time = registerTimer(info->actionset->timesteps,
+                        &schedule->timer_id,
+                        &DoScheduledGroupAction);
+
+                OC_LOG(INFO, TAG, PCF("Reregisteration."));
+#ifndef WITH_ARDUINO
+                pthread_mutex_unlock(&lock);
+#endif
+                AddScheduledResource(&scheduleResourceList, schedule);
+            }
+        }
+    }
+
+    RemoveScheduledResource(&scheduleResourceList, info);
+
+    exit:
+
+    return;
+}
+
+OCStackResult BuildCollectionGroupActionJSONResponse(
+        OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
+        OCEntityHandlerRequest *ehRequest)
 {
     OCStackResult stackRet = OC_STACK_ERROR;
 
     OC_LOG(INFO, TAG, PCF("Group Action is requested."));
     // if (stackRet == OC_STACK_OK)
     {
-
         char *doWhat = NULL;
-        char *actionName = NULL;
+        char *details = NULL;
 
         size_t bufferLength = 0;
-        unsigned char buffer[MAX_RESPONSE_LENGTH] =
-        { 0 };
+        unsigned char buffer[MAX_RESPONSE_LENGTH] = { 0 };
         unsigned char *bufferPtr = NULL;
 
         bufferPtr = buffer;
@@ -705,6 +1052,17 @@ OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHa
 
         char *jsonResponse;
 
+        stackRet = ExtractKeyValueFromRequest((char *) ehRequest->reqJSONPayload,
+                &doWhat, &details);
+
+        if(stackRet != OC_STACK_OK)
+        {
+            OC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
+            return stackRet;
+        }
+
+        stackRet = OC_STACK_ERROR;
+
         cJSON *json;
         cJSON *format;
 
@@ -716,12 +1074,36 @@ OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHa
 
             OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
 
-            unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
-            GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
+            if (strcmp(doWhat, ACTIONSET) == 0)
+            {
+                OCActionSet *actionSet = NULL;
+                stackRet = BuildActionSetFromString(&actionSet, details);
+
+                if(stackRet == OC_STACK_OK)
+                {
+                    if (actionSet != NULL)
+                    {
+                        stackRet = AddActionSet(&resource->actionsetHead,
+                                actionSet);
+                        if (stackRet == OC_STACK_ERROR)
+                        {
+                            if(actionSet != NULL)
+                            {
+                                DeleteActionSet( &actionSet );
+                            }
+                            OC_LOG(INFO, TAG, PCF("Duplicated ActionSet "));
+                        }
+                    }
+                }
+                else
+                {
+                    stackRet = OC_STACK_ERROR;
+                }
 
-            if (strcmp(doWhat, "DelActionSet") == 0)
+            }
+            else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
             {
-                if (FindAndDeleteActionSet(&resource, actionName) == OC_STACK_OK)
+                if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
                 {
                     stackRet = OC_STACK_OK;
                 }
@@ -739,106 +1121,165 @@ OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHa
             bufferLength = strlen((const char *) buffer);
             if (bufferLength > 0)
             {
-                OCEntityHandlerResponse response =
-                { 0 };
-                response.ehResult = OC_EH_OK;
-                response.payload = buffer;
+                OCEntityHandlerResponse response = { 0 };
+                if(stackRet == OC_STACK_OK)
+                    response.ehResult = OC_EH_OK;
+                else
+                    response.ehResult = OC_EH_ERROR;
+                response.payload = (char*)buffer;
                 response.payloadSize = bufferLength + 1;
                 response.persistentBufferFlag = 0;
-                response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+                response.requestHandle =
+                        (OCRequestHandle) ehRequest->requestHandle;
                 response.resourceHandle = (OCResourceHandle) collResource;
                 stackRet = OCDoResponse(&response);
             }
-
-            stackRet = OC_STACK_OK;
         }
 
         if (method == OC_REST_POST)
         {
-            OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
-
             OCActionSet *actionset = NULL;
-            unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
-
-            GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
 
             json = cJSON_CreateObject();
             cJSON_AddStringToObject(json, "href", resource->uri);
 
-            if (strcmp(doWhat, "DoAction") == 0)
+            if ((strcmp(doWhat, DO_ACTION) == 0)
+                    || (strcmp(doWhat, "DoScheduledAction") == 0))
             {
-                if (GetActionSet(actionName, resource->actionsetHead, &actionset) != OC_STACK_OK)
-                {
-                    OC_LOG(INFO, TAG, PCF("ERROR"));
-                    stackRet = OC_STACK_ERROR;
-                }
+                char *pActionsetName = NULL;
+                long int delay = -1;
 
-                if (actionset == NULL)
+                if (strcmp(doWhat, "DoScheduledAction") == 0)
                 {
-                    OC_LOG(INFO, TAG, PCF("ERROR"));
-                    stackRet = OC_STACK_ERROR;
+                    stackRet = ExtractActionSetNameAndDelaytime(details,
+                            &pActionsetName, &delay);
+
+                    OCFREE(details)
+                    details = pActionsetName;
                 }
                 else
                 {
+                    stackRet = OC_STACK_OK;
+                }
 
-                    OCAction *pointerAction = actionset->head;
-
-                    unsigned int num = GetNumOfTargetResource(pointerAction);
-
-                    ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
-                            HandleAggregateResponse;
-                    ((OCServerRequest *) ehRequest->requestHandle)->numResponses = num + 1;
-
-//                    printf("ActionSet Name :: %s\n", actionset->actionsetName);
-                    while (pointerAction != NULL)
+                if (stackRet == OC_STACK_OK)
+                {
+                    if (GetActionSet(details, resource->actionsetHead,
+                            &actionset) != OC_STACK_OK)
                     {
-                        unsigned char actionDesc[MAX_RESPONSE_LENGTH] = { 0 };
-                        unsigned char* actionDescPtr = actionDesc;
-                        uint16_t remaining = MAX_RESPONSE_LENGTH;
-
-                        strcpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX);
-                        BuildActionJSON(pointerAction, actionDescPtr, &remaining);
-                        strcat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX);
-
-                        ClientRequstInfo *info = (ClientRequstInfo *) OCMalloc(
-                                sizeof(ClientRequstInfo));
-                        memset(info, 0, sizeof(ClientRequstInfo));
-
-                        info->collResource = resource;
-                        info->ehRequest = (OCServerRequest *) ehRequest->requestHandle;
+                        OC_LOG(INFO, TAG, PCF("ERROR"));
+                        stackRet = OC_STACK_ERROR;
+                    }
 
-                        SendAction(&info->required, pointerAction->resourceUri, actionDescPtr);
+                    if (actionset == NULL)
+                    {
+                        OC_LOG(INFO, TAG, PCF("Cannot Find ActionSet"));
+                        stackRet = OC_STACK_ERROR;
+                    }
+                    else
+                    {
+                        OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
+                        if (actionset->type == NONE)
+                        {
+                            OC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
+                                    actionset->actionsetName);
+                            unsigned int num = GetNumOfTargetResource(
+                                    actionset->head);
+
+                            ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
+                                    HandleAggregateResponse;
+                            ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
+                                    num + 1;
+
+                            DoAction(resource, actionset,
+                                    (OCServerRequest*) ehRequest->requestHandle);
+                            stackRet = OC_STACK_OK;
+                        }
+                        else
+                        {
+                            OC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
+                                    actionset->actionsetName);
 
-                        AddClientRequestInfo(&clientRequstList, info);
+                            delay =
+                                    (delay == -1 ? actionset->timesteps : delay);
 
+                            ScheduledResourceInfo *schedule;
+                            schedule = (ScheduledResourceInfo *) OCMalloc(
+                                    sizeof(ScheduledResourceInfo));
 
-                        pointerAction = pointerAction->next;
+                            if (schedule)
+                            {
+                                OC_LOG(INFO, TAG, PCF("Building New Call Info."));
+                                memset(schedule, 0,
+                                        sizeof(ScheduledResourceInfo));
+
+                                schedule->resource = resource;
+                                schedule->actionset = actionset;
+                                schedule->ehRequest =
+                                        (OCServerRequest*) ehRequest->requestHandle;
+
+                                if (delay > 0)
+                                {
+                                    OC_LOG_V(INFO, TAG, "delay_time is %lf seconds.",
+                                            actionset->timesteps);
+
+                                    schedule->time = registerTimer(delay,
+                                            &schedule->timer_id,
+                                            &DoScheduledGroupAction);
+
+                                    AddScheduledResource(&scheduleResourceList,
+                                            schedule);
+                                    stackRet = OC_STACK_OK;
+                                }
+                                else
+                                {
+                                    stackRet = OC_STACK_ERROR;
+                                }
+                            }
+                        }
                     }
+                }
+            }
+            else if (strcmp(doWhat, "CancelAction") == 0)
+            {
+                ScheduledResourceInfo *info =
+                        GetScheduledResourceByActionSetName(scheduleResourceList, details);
 
+                if(info != NULL)
+                {
+                    unregisterTimer(info->timer_id);
 
+                    RemoveScheduledResource(&scheduleResourceList, info);
                     stackRet = OC_STACK_OK;
                 }
+                else
+                {
+                    stackRet = OC_STACK_ERROR;
+                }
             }
-            else if (strcmp(doWhat, "GetActionSet") == 0)
+
+            else if (strcmp(doWhat, GET_ACTIONSET) == 0)
             {
                 char *plainText = NULL;
                 OCActionSet *actionset = NULL;
 
-                cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
-                GetActionSet(actionName, resource->actionsetHead, &actionset);
+                cJSON_AddItemToObject(json, "rep", format =
+                        cJSON_CreateObject());
+                GetActionSet(details, resource->actionsetHead, &actionset);
                 if (actionset != NULL)
                 {
-                    GetStringFromActionSet(actionset, &plainText);
+                    BuildStringFromActionSet(actionset, &plainText);
 
                     if (plainText != NULL)
                     {
-                        cJSON_AddStringToObject(format, "ActionSet", plainText);
+                        cJSON_AddStringToObject(format, ACTIONSET, plainText);
                     }
-
+                    OCFree(plainText);
                     stackRet = OC_STACK_OK;
                 }
             }
 
+
             jsonResponse = cJSON_Print(json);
             cJSON_Delete(json);
 
@@ -847,17 +1288,23 @@ OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHa
             bufferLength = strlen((const char *) buffer);
             if (bufferLength > 0)
             {
-                OCEntityHandlerResponse response =
-                { 0 };
-                response.ehResult = OC_EH_OK;
-                response.payload = buffer;
+                OCEntityHandlerResponse response = { 0 };
+                if(stackRet == OC_STACK_OK)
+                    response.ehResult = OC_EH_OK;
+                else
+                    response.ehResult = OC_EH_ERROR;
+                response.payload = (char *)buffer;
                 response.payloadSize = bufferLength + 1;
                 response.persistentBufferFlag = 0;
-                response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+                response.requestHandle =
+                        (OCRequestHandle) ehRequest->requestHandle;
                 response.resourceHandle = (OCResourceHandle) collResource;
                 stackRet = OCDoResponse(&response);
             }
         }
+
+        OCFREE(doWhat)
+        OCFREE(details)
     }
 
     return stackRet;