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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
31 #include "GroupManager.h"
33 #define PLAIN_DELIMITER "\""
34 #define ACTION_DELIMITER "*"
35 #define DESC_DELIMITER "|"
36 #define ATTR_DELIMITER "="
41 std::map< std::vector< std::string >, CandidateCallback > candidateRequest;
42 std::map< std::vector< std::string >, CandidateCallback > candidateRequestForTimer;
43 std::map< std::string, std::map< std::string, std::shared_ptr< OCResource > > > rtForResourceList;
44 std::vector< std::string > allFoundResourceTypes;
45 std::mutex callbackLock;
48 template< typename T >
49 bool IsSubset(std::vector< T > full, std::vector< T > sub)
51 std::sort(full.begin(), full.end());
52 std::sort(sub.begin(), sub.end());
53 return std::includes(full.begin(), full.end(), sub.begin(), sub.end());
55 std::vector< std::string > &str_split(const std::string &s, char delim,
56 std::vector< std::string > &elems)
58 std::stringstream ss(s);
60 while (std::getline(ss, item, delim))
62 elems.push_back(item);
67 std::vector< std::string > str_split(const std::string &s, char delim)
69 std::vector< std::string > elems;
70 str_split(s, delim, elems);
74 void GroupManager::onFoundResource(std::shared_ptr< OCResource > resource, int waitsec)
77 std::string resourceURI;
78 std::string hostAddress;
81 // Do some operations with resource object.
85 std::cout << "DISCOVERED Resource:" << std::endl;
86 // Get the resource URI
87 resourceURI = resource->uri();
88 std::cout << "\tURI of the resource: " << resourceURI << std::endl;
90 // Get the resource host address
91 hostAddress = resource->host();
92 std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
94 // Get the resource types
95 std::cout << "\tList of resource types: " << std::endl;
97 hostAddress.append(resourceURI);
99 for (auto &resourceTypes : resource->getResourceTypes())
101 std::cout << "\t\t" << resourceTypes << std::endl;
103 if (std::find(allFoundResourceTypes.begin(), allFoundResourceTypes.end(),
104 resourceTypes) == allFoundResourceTypes.end())
106 allFoundResourceTypes.push_back(resourceTypes);
109 rtForResourceList[resourceTypes][hostAddress] = resource;
112 // Get the resource interfaces
113 std::cout << "\tList of resource interfaces: " << std::endl;
114 for (auto &resourceInterfaces : resource->getResourceInterfaces())
116 std::cout << "\t\t" << resourceInterfaces << std::endl;
121 findPreparedRequest(candidateRequest);
126 // Resource is invalid
127 std::cout << "Resource is invalid" << std::endl;
131 catch (std::exception& e)
137 GroupManager::GroupManager(void)
145 GroupManager::~GroupManager(void)
147 candidateRequest.clear();
148 candidateRequestForTimer.clear();
149 rtForResourceList.clear();
150 allFoundResourceTypes.clear();
153 void GroupManager::findPreparedRequest(
154 std::map< std::vector< std::string >, CandidateCallback > &request)
156 std::lock_guard<std::mutex> lock(callbackLock);
157 std::vector< std::shared_ptr< OCResource > > resources;
159 for (auto it = request.begin(); it != request.end();)
162 if (IsSubset(allFoundResourceTypes, it->first))
164 for (unsigned int i = 0; i < it->first.size(); ++i)
167 for (auto secondIt = rtForResourceList[it->first.at(i)].begin();
168 secondIt != rtForResourceList[it->first.at(i)].end(); ++secondIt)
170 //insert resource related to request
171 resources.push_back(secondIt->second);
175 it->second(resources);
177 //TODO : decide policy - callback only once
189 void GroupManager::lazyCallback(int second)
192 findPreparedRequest(candidateRequestForTimer);
196 OCStackResult GroupManager::findCandidateResources(
197 std::vector< std::string > resourceTypes,
198 CandidateCallback callback, int waitsec)
200 if (resourceTypes.size() < 1)
202 return OC_STACK_ERROR;
206 return OC_STACK_ERROR;
209 std::sort(resourceTypes.begin(), resourceTypes.end());
210 resourceTypes.erase(std::unique(resourceTypes.begin(), resourceTypes.end()),
211 resourceTypes.end());
215 candidateRequestForTimer.insert(std::make_pair(resourceTypes, callback));
219 candidateRequest.insert(std::make_pair(resourceTypes, callback));
222 for (unsigned int i = 0; i < resourceTypes.size(); ++i)
224 // std::cout << "resourceTypes : " << resourceTypes.at(i) << std::endl;
226 std::string query = OC_RSRVD_WELL_KNOWN_URI;
227 query.append("?rt=");
228 query.append(resourceTypes.at(i));
230 OCPlatform::findResource("",
233 std::function < void(std::shared_ptr < OCResource > resource)
234 > (std::bind(&GroupManager::onFoundResource, this, std::placeholders::_1,
241 std::function< void(int second) >(
242 std::bind(&GroupManager::lazyCallback, this, std::placeholders::_1)),
251 OCStackResult GroupManager::bindResourceToGroup(OCResourceHandle& childHandle, std::shared_ptr< OCResource > resource, OCResourceHandle& collectionHandle)
254 OCStackResult result = OCPlatform::registerResource(childHandle, resource);
256 cout << "\tresource registed!" << endl;
258 if(result == OC_STACK_OK)
260 OCPlatform::bindResource(collectionHandle, childHandle);
264 cout << "\tresource Error!" << endl;
276 std::map< std::string, CollectionPresenceCallback > presenceCallbacks;
278 // Callback to presence
279 void GroupManager::collectionPresenceHandler(OCStackResult result, const unsigned int nonce,
280 const std::string& hostAddress, std::string host, std::string uri)
282 std::cout << "uri : " << uri << std::endl;
283 std::cout << "host : " << host << std::endl;
284 std::cout << "result : " << result << std::endl;
288 std::cout << "Nonce# " << nonce << std::endl;
290 case OC_STACK_PRESENCE_STOPPED:
291 std::cout << "Presence Stopped\n";
293 case OC_STACK_PRESENCE_DO_NOT_HANDLE:
294 std::cout << "Presence do not handle\n";
296 case OC_STACK_PRESENCE_TIMEOUT:
297 std::cout << "Presence TIMEOUT\n";
300 std::cout << "Error\n";
304 if (presenceCallbacks.find(uri) != presenceCallbacks.end())
306 (presenceCallbacks.find(uri)->second)(uri, result);
310 void GroupManager::checkCollectionRepresentation(const OCRepresentation& rep,
311 CollectionPresenceCallback callback)
313 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
315 std::vector< OCRepresentation > children = rep.getChildren();
316 if(children.size() == 0 )
318 callback("", OC_STACK_ERROR);
322 for (auto oit = children.begin(); oit != children.end(); ++oit)
324 if(oit->getUri().find("coap://") == std::string::npos)
326 std::cout << "The resource with a URI " << oit->getUri() << " is not a remote resource."
327 << " Thus, we ignore to send a request for presence check to the resource.\n";
332 std::vector< std::string > hostAddressVector = str_split(oit->getUri(), '/');
333 std::string hostAddress = "";
334 for (unsigned int i = 0; i < hostAddressVector.size(); ++i)
338 hostAddress.append(hostAddressVector.at(i));
341 hostAddress.append("/");
346 std::vector< std::string > resourceTypes = oit->getResourceTypes();
347 // for (unsigned int i = 0; i < resourceTypes.size(); ++i)
349 // std::cout << "\t\t\tresourcetype :" << resourceTypes.at(i) << std::endl;
352 // std::string resourceType = "core.";
353 // resourceType.append(str_split(oit->getUri(), '/').at(4));
354 // std::cout << "\t\tconvertRT : " << resourceType << std::endl;
355 // std::cout << "\t\tresource type front : " << resourceTypes.front() << endl;
356 // std::cout << "\t\thost : " << hostAddress << std::endl;
357 OCPlatform::OCPresenceHandle presenceHandle;
358 OCStackResult result = OC_STACK_ERROR;
362 result = OCPlatform::subscribePresence(presenceHandle, hostAddress,
364 resourceTypes.front(),
367 void(OCStackResult result, const unsigned int nonce,
368 const std::string& hostAddress) >(
369 std::bind(&GroupManager::collectionPresenceHandler, this,
370 std::placeholders::_1, std::placeholders::_2,
371 std::placeholders::_3, hostAddress, oit->getUri())));
372 }catch(OCException& e)
374 std::cout<< "Exception in subscribePresence: "<< e.what() << std::endl;
377 if (result == OC_STACK_OK)
379 presenceCallbacks.insert(std::make_pair(oit->getUri(), callback));
383 callback("", OC_STACK_ERROR);
388 void GroupManager::onGetForPresence(const HeaderOptions& headerOptions,
389 const OCRepresentation& rep, const int eCode, CollectionPresenceCallback callback)
391 if (eCode == OC_STACK_OK)
393 std::cout << "GET request was successful" << std::endl;
394 std::cout << "Resource URI: " << rep.getUri() << std::endl;
396 checkCollectionRepresentation(rep, callback);
401 std::cout << "onGET Response error: " << eCode << std::endl;
402 callback("", OC_STACK_ERROR);
406 OCStackResult GroupManager::subscribeCollectionPresence(
407 std::shared_ptr< OCResource > collectionResource, CollectionPresenceCallback callback)
409 if(callback == NULL || collectionResource == NULL)
411 return OC_STACK_ERROR;
414 OCStackResult result = OC_STACK_OK;
415 //callback("core.room",OC_STACK_OK);
417 QueryParamsMap queryParam;
419 //parameter 1 = resourceType
420 collectionResource->get("", DEFAULT_INTERFACE, queryParam,
422 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
424 std::bind(&GroupManager::onGetForPresence, this, std::placeholders::_1,
425 std::placeholders::_2, std::placeholders::_3, callback)));
434 std::string GroupManager::getStringFromActionSet(const ActionSet *newActionSet)
436 std::string message = "";
438 if(newActionSet == NULL)
441 message = newActionSet->actionsetName;
443 message.append(newActionSet->toString());
445 for (auto iterAction = newActionSet->listOfAction.begin();
446 iterAction != newActionSet->listOfAction.end(); iterAction++)
448 message.append("uri=");
449 message.append((*iterAction)->target);
452 for (auto iterCapa = (*iterAction)->listOfCapability.begin();
453 iterCapa != (*iterAction)->listOfCapability.end(); iterCapa++)
455 message.append((*iterCapa)->capability);
457 message.append((*iterCapa)->status);
459 if (iterCapa + 1 != (*iterAction)->listOfCapability.end())
463 if (iterAction + 1 != newActionSet->listOfAction.end())
472 #define DELETE(p) { \
477 #define DELETEARRAY(p) { \
482 ActionSet* GroupManager::getActionSetfromString(std::string description)
485 char *plainText = NULL;
486 char *plainPtr = NULL;
487 char *attr = NULL, *desc = NULL;
489 Action *action = NULL;
490 Capability *capa = NULL;
491 ActionSet *actionset = new ActionSet();
493 if(actionset == NULL)
498 if(description.empty())
502 else if(description.at(0) == '*')
507 plainText = new char[(description.length() + 1)];
508 strcpy(plainText, description.c_str());
510 token = strtok_r(plainText, ACTION_DELIMITER, &plainPtr);
514 actionset->actionsetName = std::string(token);
516 if((actionset->actionsetName).empty())
519 token = strtok_r(NULL, ACTION_DELIMITER, &plainPtr);
528 sscanf(token, "%ld %d", &actionset->mDelay, (int*)&actionset->type);
530 token = strtok_r(NULL, ACTION_DELIMITER, &plainPtr);
539 char *descPtr = NULL;
540 desc = new char[(strlen(token) + 1)];
545 token = strtok_r(desc, DESC_DELIMITER, &descPtr);
547 while (token != NULL)
549 char *attrPtr = NULL;
550 attr = new char[(strlen(token) + 1)];
554 token = strtok_r(attr, ATTR_DELIMITER, &attrPtr);
555 while (token != NULL)
557 if ( (action == NULL) && strcmp(token, "uri") == 0) //consider only first "uri" as uri, other as attribute.
559 token = strtok_r(NULL, ATTR_DELIMITER, &attrPtr);
565 action = new Action();
568 action->target = std::string(token);
577 capa = new Capability();
578 capa->capability = std::string(token);
579 token = strtok_r(NULL, ATTR_DELIMITER, &attrPtr);
584 capa->status = std::string(token);
587 action->listOfCapability.push_back(capa);
592 token = strtok_r(NULL, ATTR_DELIMITER, &attrPtr);
595 token = strtok_r(NULL, DESC_DELIMITER, &descPtr);
600 actionset->listOfAction.push_back(action);
615 token = strtok_r(NULL, ACTION_DELIMITER, &plainPtr);
618 DELETEARRAY(plainText);
626 DELETEARRAY(plainText);
631 OCStackResult GroupManager::addActionSet(std::shared_ptr< OCResource > resource,
632 const ActionSet* newActionSet, PutCallback cb)
634 // BUILD message of ActionSet which it is included delimiter.
635 if ((resource != NULL) && (newActionSet != NULL))
637 if(newActionSet->mDelay < 0)
639 return OC_STACK_INVALID_PARAM;
642 std::string message = getStringFromActionSet(newActionSet);
644 OCRepresentation rep;
645 rep.setValue("ActionSet", message);
646 return resource->put(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
647 QueryParamsMap(), cb);
651 return OC_STACK_ERROR;
655 OCStackResult GroupManager::executeActionSet(std::shared_ptr< OCResource > resource,
656 std::string actionsetName, PostCallback cb)
658 if (resource != NULL)
660 OCRepresentation rep;
662 rep.setValue("DoAction", actionsetName);
663 return resource->post(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
664 QueryParamsMap(), cb);
668 return OC_STACK_ERROR;
672 OCStackResult GroupManager::executeActionSet(std::shared_ptr< OCResource > resource,
673 std::string actionsetName, long int delay, PostCallback cb)
677 return OC_STACK_INVALID_PARAM;
679 if (resource != NULL)
681 std::string value = actionsetName;
683 value.append(std::to_string(delay));
685 OCRepresentation rep;
686 rep.setValue("DoScheduledAction", value);
687 return resource->post(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
688 QueryParamsMap(), cb);
692 return OC_STACK_ERROR;
696 OCStackResult GroupManager::cancelActionSet(std::shared_ptr< OCResource > resource,
697 std::string actionsetName, PostCallback cb)
699 if (resource != NULL)
701 OCRepresentation rep;
703 rep.setValue("CancelAction", actionsetName);
704 return resource->post(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
705 QueryParamsMap(), cb);
709 return OC_STACK_ERROR;
713 OCStackResult GroupManager::getActionSet(std::shared_ptr< OCResource > resource,
714 std::string actionsetName, PostCallback cb)
716 if (resource != NULL)
718 OCRepresentation rep;
720 rep.setValue("GetActionSet", actionsetName);
722 return resource->post(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
723 QueryParamsMap(), cb);
727 return OC_STACK_ERROR;
731 OCStackResult GroupManager::deleteActionSet(std::shared_ptr< OCResource > resource,
732 std::string actionsetName, PutCallback cb)
734 if (resource != NULL)
736 OCRepresentation rep;
738 rep.setValue("DelActionSet", actionsetName);
740 return resource->put(resource->getResourceTypes().front(), GROUP_INTERFACE, rep,
741 QueryParamsMap(), cb);
745 return OC_STACK_ERROR;