1 //******************************************************************
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #define _POSIX_C_SOURCE 200112L
23 #include "iotivity_config.h"
29 #include "ocpayload.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
33 #include "occollection.h"
37 #define TAG "OIC_RI_GROUP"
39 #define DESC_DELIMITER "\""
40 #define ACTION_DELIMITER "*"
41 #define ATTR_DELIMITER "|"
42 #define ATTR_ASSIGN "="
44 // Definitions for operations related to actions
45 #define DO_ACTION "DoAction"
46 #define GET_ACTIONSET "GetActionSet"
47 #define ACTIONSET "ActionSet"
48 #define CANCEL_ACTIONSET "CancelAction"
49 #define DELETE_ACTIONSET "DelActionSet"
51 #define DEFAULT_CONTEXT_VALUE 0x99
53 #define VARIFY_POINTER_NULL(pointer, result, toExit) \
56 result = OC_STACK_NO_MEMORY;\
59 #define VARIFY_PARAM_NULL(pointer, result, toExit) \
62 result = OC_STACK_INVALID_PARAM;\
66 #define OCFREE(pointer) \
72 oc_mutex g_scheduledResourceLock = NULL;
76 NONE = 0, SCHEDULED, RECURSIVE
79 typedef struct scheduledresourceinfo
82 OCActionSet *actionset;
86 OCServerRequest *ehRequest;
89 struct scheduledresourceinfo* next;
90 } ScheduledResourceInfo;
92 ScheduledResourceInfo *g_scheduleResourceList = NULL;
94 void AddScheduledResource(ScheduledResourceInfo **head,
95 ScheduledResourceInfo* add)
97 OIC_LOG(INFO, TAG, "AddScheduledResource Entering...");
99 oc_mutex_lock(g_scheduledResourceLock);
100 ScheduledResourceInfo *tmp = NULL;
116 oc_mutex_unlock(g_scheduledResourceLock);
119 ScheduledResourceInfo* GetScheduledResource(ScheduledResourceInfo *head)
121 OIC_LOG(INFO, TAG, "GetScheduledResource Entering...");
123 oc_mutex_lock(g_scheduledResourceLock);
127 ScheduledResourceInfo *tmp = NULL;
130 #if !defined(WITH_ARDUINO)
141 diffTm = timespec_diff(tmp->time, t_now);
143 if (diffTm <= (time_t) 0)
145 OIC_LOG(INFO, TAG, "return Call INFO.");
155 oc_mutex_unlock(g_scheduledResourceLock);
159 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
164 ScheduledResourceInfo* GetScheduledResourceByActionSetName(ScheduledResourceInfo *head, char *setName)
166 OIC_LOG(INFO, TAG, "GetScheduledResourceByActionSetName Entering...");
168 oc_mutex_lock(g_scheduledResourceLock);
170 ScheduledResourceInfo *tmp = NULL;
177 if (strcmp(tmp->actionset->actionsetName, setName) == 0)
179 OIC_LOG(INFO, TAG, "return Call INFO.");
188 oc_mutex_unlock(g_scheduledResourceLock);
192 OIC_LOG(INFO, TAG, "Cannot Find Call Info.");
197 void RemoveScheduledResource(ScheduledResourceInfo **head,
198 ScheduledResourceInfo* del)
201 oc_mutex_lock(g_scheduledResourceLock);
203 OIC_LOG(INFO, TAG, "RemoveScheduledResource Entering...");
204 ScheduledResourceInfo *tmp = NULL;
209 oc_mutex_unlock(g_scheduledResourceLock);
216 *head = (*head)->next;
221 while (tmp->next && (tmp->next != del))
227 tmp->next = del->next;
233 oc_mutex_unlock(g_scheduledResourceLock);
236 typedef struct aggregatehandleinfo
238 OCServerRequest *ehRequest;
240 OCResource *collResource;
242 struct aggregatehandleinfo *next;
245 ClientRequestInfo *clientRequstList = NULL;
247 void AddClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* add)
249 ClientRequestInfo *tmp = NULL;
267 ClientRequestInfo* GetClientRequestInfo(ClientRequestInfo *head,
270 ClientRequestInfo *tmp = NULL;
278 if (tmp->required == handle)
291 void RemoveClientRequestInfo(ClientRequestInfo **head, ClientRequestInfo* del)
293 ClientRequestInfo *tmp = NULL;
300 *head = (*head)->next;
305 while (tmp->next && (tmp->next != del))
311 tmp->next = del->next;
316 void AddCapability(OCCapability** head, OCCapability* node)
318 OCCapability *pointer = *head;
325 while (pointer->next != NULL)
327 pointer = pointer->next;
330 pointer->next = node;
334 void AddAction(OCAction** head, OCAction* node)
336 OCAction *pointer = *head;
344 while (pointer->next != NULL)
346 pointer = pointer->next;
349 pointer->next = node;
353 OCStackResult AddActionSet(OCActionSet **head, OCActionSet* node)
355 OCActionSet *pointer = *head;
356 OCActionSet *prev = NULL;
359 return OC_STACK_ERROR;
368 while (pointer != NULL)
370 // check the uniqeness of actionsetname.
371 if (strcmp(pointer->actionsetName, node->actionsetName) == 0)
373 return OC_STACK_ERROR;
377 pointer = pointer->next;
386 void DeleteCapability(OCCapability *del)
388 OCFREE(del->capability)
389 del->capability = NULL;
395 void DeleteAction(OCAction** action)
397 OCCapability* pointer = (*action)->head;
398 OCCapability* pDel = NULL;
403 pointer = pointer->next;
405 DeleteCapability(pDel);
407 OCFREE((*action)->resourceUri)
408 (*action)->next = NULL;
412 void DeleteActionSet(OCActionSet** actionset)
414 OCAction* pointer = NULL;
415 OCAction* pDel = NULL;
417 if(*actionset == NULL)
420 pointer = (*actionset)->head;
425 pointer = pointer->next;
429 // (*actionset)->head = NULL;
430 OCFREE((*actionset)->actionsetName)
434 OCStackResult FindAndDeleteActionSet(OCResource **resource,
435 const char * actionsetName)
437 if (*resource != NULL)
439 OCActionSet *pointer = NULL;
440 OCActionSet *pDel = NULL;
442 pointer = (*resource)->actionsetHead;
446 return OC_STACK_ERROR;
450 if (strcmp(pointer->actionsetName, actionsetName) == 0)
452 if (pointer->next != NULL)
453 (*resource)->actionsetHead = pointer->next;
455 (*resource)->actionsetHead = NULL;
457 DeleteActionSet(&pointer);
459 else if (pointer->next != NULL)
463 if (pointer->next != NULL)
465 if (strcmp(pointer->next->actionsetName, actionsetName)
468 pDel = pointer->next;
469 pointer->next = pointer->next->next;
471 DeleteActionSet(&pDel);
474 pointer = pointer->next;
482 return OC_STACK_ERROR;
485 OCStackResult GetActionSet(const char *actionName, OCActionSet *head,
486 OCActionSet** actionset)
488 OCActionSet *pointer = head;
492 if (strcmp(pointer->actionsetName, actionName) == 0)
494 *actionset = pointer;
498 pointer = pointer->next;
501 return OC_STACK_ERROR;
505 OCStackResult ExtractKeyValueFromRequest(OCEntityHandlerRequest *ehRequest,
506 char **key, char **value)
508 OCStackResult result = OC_STACK_OK;
510 char *actionSetStr = NULL;
512 if( NULL == ehRequest->payload )
514 result = OC_STACK_ERROR;
520 input = (OCRepPayload*)(ehRequest->payload);
522 if(OCRepPayloadGetPropString(input, ACTIONSET, &actionSetStr))
524 *key = OICStrdup(ACTIONSET);
525 VARIFY_POINTER_NULL(*key, result, exit);
527 *value = OICStrdup(actionSetStr);
528 VARIFY_POINTER_NULL(*value, result, exit);
530 else if(OCRepPayloadGetPropString(input, DO_ACTION, &actionSetStr))
532 *key = OICStrdup(DO_ACTION);
533 VARIFY_POINTER_NULL(*key, result, exit);
535 *value = OICStrdup(actionSetStr);
536 VARIFY_POINTER_NULL(*value, result, exit);
538 else if(OCRepPayloadGetPropString(input, GET_ACTIONSET, &actionSetStr))
540 *key = OICStrdup(GET_ACTIONSET);
541 VARIFY_POINTER_NULL(*key, result, exit);
543 *value = OICStrdup(actionSetStr);
544 VARIFY_POINTER_NULL(*value, result, exit);
546 else if(OCRepPayloadGetPropString(input, DELETE_ACTIONSET, &actionSetStr))
548 *key = OICStrdup(DELETE_ACTIONSET);
549 VARIFY_POINTER_NULL(*key, result, exit);
551 *value = OICStrdup(actionSetStr);
552 VARIFY_POINTER_NULL(*value, result, exit);
554 else if(OCRepPayloadGetPropString(input, CANCEL_ACTIONSET, &actionSetStr))
556 *key = OICStrdup(CANCEL_ACTIONSET);
557 VARIFY_POINTER_NULL(*key, result, exit);
559 *value = OICStrdup(actionSetStr);
560 VARIFY_POINTER_NULL(*value, result, exit);
564 result = OC_STACK_ERROR;
568 if (result != OC_STACK_OK)
574 OCFREE(actionSetStr);
579 OCStackResult ExtractActionSetNameAndDelaytime(char *pChar, char **setName,
582 char *token = NULL, *tokenPtr = NULL;
583 OCStackResult result = OC_STACK_OK;
585 token = (char*) strtok_r(pChar, ACTION_DELIMITER, &tokenPtr);
586 VARIFY_POINTER_NULL(token, result, exit)
588 *setName = (char *) OICMalloc(strlen(token) + 1);
589 VARIFY_POINTER_NULL(*setName, result, exit)
590 VARIFY_PARAM_NULL(token, result, exit)
591 strncpy(*setName, token, strlen(token) + 1);
593 token = strtok_r(NULL, ACTION_DELIMITER, &tokenPtr);
594 VARIFY_POINTER_NULL(pa, result, exit)
595 VARIFY_PARAM_NULL(token, result, exit)
605 OCStackResult BuildActionSetFromString(OCActionSet **set, char* actiondesc)
607 OCStackResult result = OC_STACK_OK;
609 char *iterToken = NULL, *iterTokenPtr = NULL;
610 char *descIterToken = NULL, *descIterTokenPtr = NULL;
611 char *attrIterToken = NULL, *attrIterTokenPtr = NULL;
612 char *desc = NULL, *attr = NULL;
613 char *key = NULL, *value = NULL;
615 OCAction *action = NULL;
616 OCCapability *capa = NULL;
618 OIC_LOG(INFO, TAG, "Build ActionSet Instance.");
620 *set = (OCActionSet*) OICMalloc(sizeof(OCActionSet));
621 VARIFY_POINTER_NULL(*set, result, exit)
623 iterToken = (char *) strtok_r(actiondesc, ACTION_DELIMITER, &iterTokenPtr);
624 VARIFY_POINTER_NULL(iterToken, result, exit);
627 memset(*set, 0, sizeof(OCActionSet));
628 (*set)->actionsetName = (char *) OICMalloc(strlen(iterToken) + 1);
629 VARIFY_POINTER_NULL((*set)->actionsetName, result, exit)
630 VARIFY_PARAM_NULL(iterToken, result, exit)
631 strncpy((*set)->actionsetName, iterToken, strlen(iterToken) + 1);
633 // Time info. for Scheduled/Recursive Group action.
634 // d is meant Day of the week.
635 // T is meant ActionType.
636 // yyyy-mm-dd hh:mm:ss d
637 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
638 VARIFY_PARAM_NULL(iterToken, result, exit)
639 #if !defined(WITH_ARDUINO)
640 if( 2 != sscanf(iterToken, "%ld %u", &(*set)->timesteps, &(*set)->type) )
642 // If the return value should be 2, the number of items in the argument. Otherwise, it fails.
647 OIC_LOG_V(INFO, TAG, "ActionSet Name : %s", (*set)->actionsetName);
649 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
652 desc = (char *) OICMalloc(strlen(iterToken) + 1);
653 VARIFY_POINTER_NULL(desc, result, exit)
654 VARIFY_PARAM_NULL(desc, result, exit)
655 strncpy(desc, iterToken, strlen(iterToken) + 1);
656 descIterToken = (char *) strtok_r(desc, ATTR_DELIMITER,
658 while (descIterToken)
660 attr = (char *) OICMalloc(strlen(descIterToken) + 1);
661 VARIFY_POINTER_NULL(attr, result, exit)
662 VARIFY_PARAM_NULL(descIterToken, result, exit)
663 strncpy(attr, descIterToken, strlen(descIterToken) + 1);
665 attrIterToken = (char *) strtok_r(attr, ATTR_ASSIGN,
667 VARIFY_POINTER_NULL(attrIterToken, result, exit);
669 key = (char *) OICMalloc(strlen(attrIterToken) + 1);
670 VARIFY_POINTER_NULL(key, result, exit)
671 VARIFY_PARAM_NULL(attrIterToken, result, exit)
672 strncpy(key, attrIterToken, strlen(attrIterToken) + 1);
674 attrIterToken = (char *) strtok_r(NULL, ATTR_ASSIGN,
676 VARIFY_POINTER_NULL(attrIterToken, result, exit);
677 value = (char *) OICMalloc(strlen(attrIterToken) + 1);
678 VARIFY_POINTER_NULL(value, result, exit)
679 VARIFY_PARAM_NULL(attrIterToken, result, exit)
680 strncpy(value, attrIterToken, strlen(attrIterToken) + 1);
682 if (strcmp(key, "uri") == 0)
684 OIC_LOG(INFO, TAG, "Build OCAction Instance.");
686 action = (OCAction*) OICMalloc(sizeof(OCAction));
687 VARIFY_POINTER_NULL(action, result, exit)
688 memset(action, 0, sizeof(OCAction));
689 action->resourceUri = (char *) OICMalloc(strlen(value) + 1);
690 VARIFY_POINTER_NULL(action->resourceUri, result, exit)
691 VARIFY_PARAM_NULL(value, result, exit)
692 strncpy(action->resourceUri, value, strlen(value) + 1);
696 if ((key != NULL) && (value != NULL))
698 OIC_LOG(INFO, TAG, "Build OCCapability Instance.");
700 capa = (OCCapability*) OICMalloc(sizeof(OCCapability));
701 VARIFY_POINTER_NULL(capa, result, exit)
702 memset(capa, 0, sizeof(OCCapability));
704 capa->capability = (char *) OICMalloc(strlen(key) + 1);
705 VARIFY_POINTER_NULL(capa->capability, result, exit)
706 VARIFY_PARAM_NULL(key, result, exit)
707 strncpy(capa->capability, key, strlen(key) + 1);
709 capa->status = (char *) OICMalloc(strlen(value) + 1);
710 VARIFY_POINTER_NULL(capa->status, result, exit)
711 VARIFY_PARAM_NULL(value, result, exit)
712 strncpy(capa->status, value, strlen(value) + 1);
714 VARIFY_POINTER_NULL(action, result, exit)
716 AddCapability(&action->head, capa);
724 descIterToken = (char *) strtok_r(NULL, ATTR_DELIMITER,
728 AddAction(&(*set)->head, action);
729 iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterTokenPtr);
747 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
749 // Can't use the macros here as they are hardcoded to 'exit' and will
750 // result in dereferencing a null pointer.
751 if (!actionset || !desc)
753 return OC_STACK_INVALID_PARAM;
755 char temp[1024] = { 0 };
756 size_t remaining = sizeof(temp) - 1;
757 OCStackResult res = OC_STACK_ERROR;
758 char* actionTypeStr = NULL;
760 OCAction *action = actionset->head;
762 if (remaining >= strlen(actionset->actionsetName) + 1)
764 strncat(temp, actionset->actionsetName, strlen(actionset->actionsetName));
765 remaining -= strlen(actionset->actionsetName);
766 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
771 res = OC_STACK_ERROR;
775 actionTypeStr = (char *)OICMalloc(1024);
776 if(actionTypeStr != NULL)
778 sprintf(actionTypeStr, "%ld %u", actionset->timesteps, actionset->type);
779 if(remaining >= strlen(actionTypeStr) + strlen(ACTION_DELIMITER) + 1)
781 strncat(temp, actionTypeStr, strlen(actionTypeStr));
782 remaining -= strlen(actionTypeStr);
783 strncat(temp, ACTION_DELIMITER, strlen(ACTION_DELIMITER));
784 remaining -= strlen(ACTION_DELIMITER);
785 OICFree(actionTypeStr);
789 OICFree(actionTypeStr);
790 res = OC_STACK_ERROR;
796 res = OC_STACK_ERROR;
800 while (action != NULL)
802 if (remaining < (strlen("uri=") + strlen(action->resourceUri) + 1))
804 res = OC_STACK_ERROR;
808 strcat(temp, "uri=");
809 remaining -= strlen("uri=");
810 strcat(temp, action->resourceUri);
811 remaining -= strlen(action->resourceUri);
815 OCCapability *capas = action->head;
816 while (capas != NULL)
818 if (remaining < (strlen(capas->capability)
819 + 1 + strlen(capas->status)))
821 res = OC_STACK_ERROR;
825 strcat(temp, capas->capability);
826 remaining -= strlen(capas->capability);
829 strcat(temp, capas->status);
830 remaining -= strlen(capas->status);
837 res = OC_STACK_ERROR;
845 action = action->next;
848 if (remaining < strlen(ACTION_DELIMITER))
850 res = OC_STACK_ERROR;
853 strcat(temp, ACTION_DELIMITER);
858 *desc = OICStrdup(temp);
859 VARIFY_POINTER_NULL(*desc, res, exit);
868 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
869 OCClientResponse* clientResponse)
872 (void)clientResponse;
873 OIC_LOG(INFO, TAG, "Entering ActionSetCB");
875 ClientRequestInfo *info = GetClientRequestInfo(clientRequstList, handle);
879 OCEntityHandlerResponse response = { 0 };
881 response.ehResult = OC_EH_OK;
883 if(NULL == clientResponse->payload)
885 OIC_LOG(ERROR, TAG, "Error sending response");
886 return OC_STACK_DELETE_TRANSACTION;
889 // Format the response. Note this requires some info about the request
890 response.requestHandle = info->ehRequest;
891 response.resourceHandle = info->collResource;
892 response.payload = clientResponse->payload;
893 response.numSendVendorSpecificHeaderOptions = 0;
894 memset(response.sendVendorSpecificHeaderOptions, 0,
895 sizeof response.sendVendorSpecificHeaderOptions);
896 memset(response.resourceUri, 0, sizeof response.resourceUri);
897 // Indicate that response is NOT in a persistent buffer
898 response.persistentBufferFlag = 0;
901 if (OCDoResponse(&response) != OC_STACK_OK)
903 OIC_LOG(ERROR, TAG, "Error sending response");
904 return OC_STACK_DELETE_TRANSACTION;
907 RemoveClientRequestInfo(&clientRequstList, info);
911 return OC_STACK_KEEP_TRANSACTION;
914 void ActionSetCD(void *context)
919 OCPayload* BuildActionCBOR(OCAction* action)
921 OCRepPayload* payload = OCRepPayloadCreate();
925 OIC_LOG(INFO, TAG, "Failed to create put payload object");
929 OCCapability* pointerCapa = action->head;
932 OCRepPayloadSetPropString(payload, pointerCapa->capability, pointerCapa->status);
933 pointerCapa = pointerCapa->next;
936 return (OCPayload*) payload;
939 uint8_t GetNumOfTargetResource(OCAction *actionset)
941 uint8_t numOfResource = 0;
943 OCAction *pointerAction = actionset;
945 while (pointerAction != NULL)
947 assert(numOfResource < UINT8_MAX);
950 pointerAction = pointerAction->next;
953 return numOfResource;
956 OCStackResult SendAction(OCDoHandle *handle, OCServerRequest* requestHandle, const char *targetUri,
960 OCCallbackData cbData;
961 cbData.cb = &ActionSetCB;
962 cbData.context = (void*)DEFAULT_CONTEXT_VALUE;
965 return OCDoResource(handle, OC_REST_PUT, targetUri, &requestHandle->devAddr,
966 payload, CT_ADAPTER_IP, OC_NA_QOS, &cbData, NULL, 0);
969 OCStackResult DoAction(OCResource* resource, OCActionSet* actionset,
970 OCServerRequest* requestHandle)
972 OCStackResult result = OC_STACK_ERROR;
974 if( NULL == actionset->head)
979 OCAction *pointerAction = actionset->head;
981 while (pointerAction != NULL)
984 payload = BuildActionCBOR(pointerAction);
991 ClientRequestInfo *info = (ClientRequestInfo *) OICMalloc(
992 sizeof(ClientRequestInfo));
997 return OC_STACK_NO_MEMORY;
1000 memset(info, 0, sizeof(ClientRequestInfo));
1002 info->collResource = resource;
1003 info->ehRequest = requestHandle;
1005 result = SendAction(&info->required, info->ehRequest, pointerAction->resourceUri,
1008 if (result != OC_STACK_OK)
1014 AddClientRequestInfo(&clientRequstList, info);
1016 pointerAction = pointerAction->next;
1022 void DoScheduledGroupAction()
1024 OIC_LOG(INFO, TAG, "DoScheduledGroupAction Entering...");
1025 ScheduledResourceInfo* info = GetScheduledResource(g_scheduleResourceList);
1029 OIC_LOG(INFO, TAG, "Target resource is NULL");
1032 else if (info->resource == NULL)
1034 OIC_LOG(INFO, TAG, "Target resource is NULL");
1037 else if (info->actionset == NULL)
1039 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1042 else if (info->ehRequest == NULL)
1044 OIC_LOG(INFO, TAG, "Target ActionSet is NULL");
1048 oc_mutex_lock(g_scheduledResourceLock);
1050 DoAction(info->resource, info->actionset, info->ehRequest);
1052 oc_mutex_unlock(g_scheduledResourceLock);
1055 if (info->actionset->type == RECURSIVE)
1057 ScheduledResourceInfo *schedule;
1058 schedule = (ScheduledResourceInfo *) OICMalloc(
1059 sizeof(ScheduledResourceInfo));
1063 OIC_LOG(INFO, TAG, "Building New Call Info.");
1064 memset(schedule, 0, sizeof(ScheduledResourceInfo));
1066 if (info->actionset->timesteps > 0)
1068 oc_mutex_lock(g_scheduledResourceLock);
1069 schedule->resource = info->resource;
1070 schedule->actionset = info->actionset;
1071 schedule->ehRequest = info->ehRequest;
1073 schedule->time = registerTimer(info->actionset->timesteps,
1074 &schedule->timer_id,
1075 &DoScheduledGroupAction);
1077 OIC_LOG(INFO, TAG, "Reregistration.");
1078 oc_mutex_unlock(g_scheduledResourceLock);
1079 AddScheduledResource(&g_scheduleResourceList, schedule);
1088 RemoveScheduledResource(&g_scheduleResourceList, info);
1095 OCStackResult BuildCollectionGroupActionCBORResponse(
1096 OCMethod method/*OCEntityHandlerFlag flag*/, OCResource *resource,
1097 OCEntityHandlerRequest *ehRequest)
1099 OCStackResult stackRet = OC_STACK_ERROR;
1101 OIC_LOG(INFO, TAG, "Group Action is requested.");
1103 char *doWhat = NULL;
1104 char *details = NULL;
1106 assert(g_scheduledResourceLock != NULL);
1108 stackRet = ExtractKeyValueFromRequest(ehRequest, &doWhat, &details);
1110 if(stackRet != OC_STACK_OK)
1112 OIC_LOG_V(ERROR, TAG, "ExtractKeyValueFromRequest failed: %d", stackRet);
1116 stackRet = OC_STACK_ERROR;
1118 if (method == OC_REST_PUT)
1120 OIC_LOG(INFO, TAG, "Group Action[PUT].");
1122 if (strcmp(doWhat, ACTIONSET) == 0)
1124 OCActionSet *actionSet = NULL;
1125 stackRet = BuildActionSetFromString(&actionSet, details);
1127 if(stackRet == OC_STACK_OK)
1129 if (actionSet != NULL)
1131 stackRet = AddActionSet(&resource->actionsetHead,
1133 if (stackRet == OC_STACK_ERROR)
1135 if(actionSet != NULL)
1137 DeleteActionSet( &actionSet );
1139 OIC_LOG(INFO, TAG, "Duplicated ActionSet ");
1144 stackRet = OC_STACK_ERROR;
1150 stackRet = OC_STACK_ERROR;
1154 else if (strcmp(doWhat, DELETE_ACTIONSET) == 0)
1156 if (FindAndDeleteActionSet(&resource, details) == OC_STACK_OK)
1158 stackRet = OC_STACK_OK;
1162 stackRet = OC_STACK_ERROR;
1166 OCRepPayload* payload = OCRepPayloadCreate();
1170 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1171 stackRet = OC_STACK_ERROR;
1175 OCEntityHandlerResponse response = { 0 };
1177 if(stackRet == OC_STACK_OK)
1178 response.ehResult = OC_EH_OK;
1180 response.ehResult = OC_EH_ERROR;
1182 // Format the response. Note this requires some info about the request
1183 response.requestHandle = ehRequest->requestHandle;
1184 response.resourceHandle = ehRequest->resource;
1185 response.payload = (OCPayload*) payload;
1186 response.numSendVendorSpecificHeaderOptions = 0;
1187 memset(response.sendVendorSpecificHeaderOptions, 0,
1188 sizeof response.sendVendorSpecificHeaderOptions);
1189 memset(response.resourceUri, 0, sizeof response. resourceUri);
1190 // Indicate that response is NOT in a persistent buffer
1191 response.persistentBufferFlag = 0;
1192 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1194 // Send the response
1195 if (OCDoResponse(&response) != OC_STACK_OK)
1197 OIC_LOG(ERROR, TAG, "Error sending response");
1198 stackRet = OC_STACK_ERROR;
1202 else if (method == OC_REST_POST)
1204 OCActionSet *actionset = NULL;
1206 OCRepPayload* payload = OCRepPayloadCreate();
1207 OCRepPayloadSetUri(payload, resource->uri);
1209 if ((strcmp(doWhat, DO_ACTION) == 0)
1210 || (strcmp(doWhat, "DoScheduledAction") == 0))
1212 char *pActionsetName = NULL;
1213 long int delay = -1;
1215 if (strcmp(doWhat, "DoScheduledAction") == 0)
1217 stackRet = ExtractActionSetNameAndDelaytime(details,
1218 &pActionsetName, &delay);
1221 details = pActionsetName;
1225 stackRet = OC_STACK_OK;
1228 if (stackRet == OC_STACK_OK)
1230 if (GetActionSet(details, resource->actionsetHead,
1231 &actionset) != OC_STACK_OK)
1233 OIC_LOG(INFO, TAG, "ERROR");
1234 stackRet = OC_STACK_ERROR;
1237 if (actionset == NULL)
1239 OIC_LOG(INFO, TAG, "Cannot Find ActionSet");
1240 stackRet = OC_STACK_ERROR;
1244 OIC_LOG(INFO, TAG, "Group Action[POST].");
1245 if (actionset->type == NONE)
1247 OIC_LOG_V(INFO, TAG, "Execute ActionSet : %s",
1248 actionset->actionsetName);
1249 uint8_t num = GetNumOfTargetResource(actionset->head);
1251 ((OCServerRequest *) ehRequest->requestHandle)->ehResponseHandler =
1252 HandleAggregateResponse;
1254 assert(num < UINT8_MAX);
1256 ((OCServerRequest *) ehRequest->requestHandle)->numResponses =
1259 DoAction(resource, actionset,
1260 (OCServerRequest*) ehRequest->requestHandle);
1261 stackRet = OC_STACK_OK;
1265 OIC_LOG_V(INFO, TAG, "Execute Scheduled ActionSet : %s",
1266 actionset->actionsetName);
1269 (delay == -1 ? actionset->timesteps : delay);
1271 ScheduledResourceInfo *schedule;
1272 schedule = (ScheduledResourceInfo *) OICMalloc(
1273 sizeof(ScheduledResourceInfo));
1277 OIC_LOG(INFO, TAG, "Building New Call Info.");
1279 sizeof(ScheduledResourceInfo));
1280 oc_mutex_lock(g_scheduledResourceLock);
1281 schedule->resource = resource;
1282 schedule->actionset = actionset;
1283 schedule->ehRequest =
1284 (OCServerRequest*) ehRequest->requestHandle;
1285 oc_mutex_unlock(g_scheduledResourceLock);
1288 OIC_LOG_V(INFO, TAG, "delay_time is %ld seconds.",
1289 actionset->timesteps);
1290 oc_mutex_lock(g_scheduledResourceLock);
1291 schedule->time = registerTimer(delay,
1292 &schedule->timer_id,
1293 &DoScheduledGroupAction);
1294 oc_mutex_unlock(g_scheduledResourceLock);
1295 AddScheduledResource(&g_scheduleResourceList,
1297 stackRet = OC_STACK_OK;
1301 stackRet = OC_STACK_ERROR;
1308 else if (strcmp(doWhat, "CancelAction") == 0)
1310 ScheduledResourceInfo *info =
1311 GetScheduledResourceByActionSetName(g_scheduleResourceList, details);
1315 oc_mutex_lock(g_scheduledResourceLock);
1316 unregisterTimer(info->timer_id);
1317 oc_mutex_unlock(g_scheduledResourceLock);
1319 RemoveScheduledResource(&g_scheduleResourceList, info);
1320 stackRet = OC_STACK_OK;
1324 stackRet = OC_STACK_ERROR;
1328 else if (strcmp(doWhat, GET_ACTIONSET) == 0)
1330 char *plainText = NULL;
1331 OCActionSet *tempActionSet = NULL;
1333 GetActionSet(details, resource->actionsetHead, &tempActionSet);
1334 if (tempActionSet != NULL)
1336 BuildStringFromActionSet(tempActionSet, &plainText);
1338 if (plainText != NULL)
1340 OCRepPayloadSetPropString(payload, ACTIONSET, plainText);
1343 stackRet = OC_STACK_OK;
1349 OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
1350 stackRet = OC_STACK_ERROR;
1354 OCEntityHandlerResponse response = { 0 };
1355 if(stackRet == OC_STACK_OK)
1356 response.ehResult = OC_EH_OK;
1358 response.ehResult = OC_EH_ERROR;
1360 // Format the response. Note this requires some info about the request
1361 response.requestHandle = ehRequest->requestHandle;
1362 response.resourceHandle = ehRequest->resource;
1363 response.payload = (OCPayload*) payload;
1364 response.numSendVendorSpecificHeaderOptions = 0;
1365 memset(response.sendVendorSpecificHeaderOptions, 0,
1366 sizeof response.sendVendorSpecificHeaderOptions);
1367 memset(response.resourceUri, 0, sizeof response.resourceUri);
1368 // Indicate that response is NOT in a persistent buffer
1369 response.persistentBufferFlag = 0;
1370 response.ehResult = (stackRet == OC_STACK_OK)?OC_EH_OK:OC_EH_ERROR;
1372 // Send the response
1373 if (OCDoResponse(&response) != OC_STACK_OK)
1375 OIC_LOG(ERROR, TAG, "Error sending response");
1376 stackRet = OC_STACK_ERROR;
1389 OCStackResult InitializeScheduleResourceList()
1391 assert(g_scheduledResourceLock == NULL);
1393 g_scheduledResourceLock = oc_mutex_new();
1394 if (g_scheduledResourceLock == NULL)
1396 return OC_STACK_ERROR;
1399 g_scheduleResourceList = NULL;
1403 void TerminateScheduleResourceList()
1405 assert(g_scheduleResourceList == NULL);
1407 if (g_scheduledResourceLock != NULL)
1409 oc_mutex_free(g_scheduledResourceLock);
1410 g_scheduledResourceLock = NULL;