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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
27 #include <OCPlatform.h>
30 #include "ThingsConfiguration.h"
38 std::map< std::string, ConfigurationRequestEntry > configurationRequestTable;
39 ThingsConfiguration* ThingsConfiguration::thingsConfigurationInstance = NULL;
40 ConfigurationCallback g_bootstrapCallback;
42 ConfigurationRequestEntry::ConfigurationRequestEntry(std::string ID,
43 ConfigurationCallback callback,
44 std::shared_ptr< OCResource > resource,
45 std::string updateVal)
48 m_callback = callback;
49 m_resource = resource;
50 m_updateVal = updateVal;
53 ConfigurationUnitInfo::ConfigurationUnitInfo(std::string name,
54 std::string attribute,
58 m_attribute = attribute;
62 std::string ConfigurationUnitInfo::getJSON()
66 res = "{\"name\":\"" + m_name + "\",\"property\":\"" + m_attribute + "\"}";
71 ThingsConfiguration::ThingsConfiguration(void)
73 ConfigurationUnitInfo unit[] =
75 { "all", "All attributes", "/oic/con" },
76 { "r", "Region", "/oic/con" },
77 { "st", "System Time", "/oic/con"},
78 { "loc", "Location", "/oic/con"},
79 { "c","Currency", "/oic/con" } };
81 for (int i = 0; i < NUMCONFUNIT; i++)
82 ConfigurationUnitTable.push_back(unit[i]);
85 ThingsConfiguration::~ThingsConfiguration(void){}
87 void ThingsConfiguration::setGroupManager(GroupManager *groupmanager)
89 g_groupmanager = groupmanager;
92 ThingsConfiguration* ThingsConfiguration::getInstance()
94 if (thingsConfigurationInstance == NULL)
96 thingsConfigurationInstance = new ThingsConfiguration();
98 return thingsConfigurationInstance;
101 void ThingsConfiguration::deleteInstance()
103 if (thingsConfigurationInstance)
105 delete thingsConfigurationInstance;
106 thingsConfigurationInstance = NULL;
110 std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
112 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
114 if ((*it).m_name == name)
115 return (*it).m_attribute;
121 std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
123 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
125 if ((*it).m_name == name)
132 std::string ThingsConfiguration::getUpdateVal(std::string conf)
134 std::map< std::string, ConfigurationRequestEntry >::iterator it =
135 configurationRequestTable.find(conf);
137 if (it == configurationRequestTable.end())
140 return it->second.m_updateVal;
143 std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
145 std::map< std::string, ConfigurationRequestEntry >::iterator it =
146 configurationRequestTable.find(conf);
148 if (it == configurationRequestTable.end())
151 return it->second.m_resource;
154 ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
156 std::map< std::string, ConfigurationRequestEntry >::iterator it =
157 configurationRequestTable.find(conf);
159 if (it == configurationRequestTable.end())
162 return it->second.m_callback;
165 std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
169 res = "{\"Configuration Units\":[";
171 auto it = ConfigurationUnitTable.begin();
174 res = res + (*it).getJSON();
177 if (it == ConfigurationUnitTable.end())
188 std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
193 if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
194 newUri = oldUri.replace(f, oldUri.size(), "");
195 else if ((f = oldUri.find("/oic/")) != string::npos)
196 newUri = oldUri.replace(f, oldUri.size(), "");
201 void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
202 const OCRepresentation& rep, const int eCode, std::string conf)
204 std::shared_ptr < OCResource > resource = getResource(conf);
208 QueryParamsMap query;
210 // After deletion of the left action set, find target child resource's URIs by sending
211 // GET message. Note that, this resource is surely a collection resource which has child
213 resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
215 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
217 std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
218 std::placeholders::_1, std::placeholders::_2,
219 std::placeholders::_3, conf)));
224 void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
225 const OCRepresentation& rep, const int eCode, std::string conf)
227 if (eCode != OC_STACK_OK)
229 std::cout << "onPut Response error: " << eCode << std::endl;
230 getCallback(conf)(headerOptions, rep, eCode);
234 std::cout << "GET request was successful" << std::endl;
236 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
238 std::vector < OCRepresentation > children = rep.getChildren();
239 for (auto oit = children.begin(); oit != children.end(); ++oit)
241 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
244 // Get information by using configuration name(conf)
245 std::shared_ptr < OCResource > resource = getResource(conf);
246 std::string actionstring = conf;
247 std::string uri = getUriByConfigurationName(conf);
248 std::string attrKey = conf;
255 // In this nest, we create a new action set of which name is the configuration name.
256 // Required information consists of a host address, URI, attribute key, and
258 ActionSet *newActionSet = new ActionSet();
259 newActionSet->actionsetName = conf;
261 for (auto oit = children.begin(); oit != children.end(); ++oit)
263 Action *newAction = new Action();
265 // oit->getUri() includes a host address as well as URI.
266 // We should split these to each other and only use the host address to create
267 // a child resource's URI. Note that the collection resource and its child
268 // resource are located in same host.
269 newAction->target = getHostFromURI(oit->getUri()) + uri;
271 Capability *newCapability = new Capability();
272 newCapability->capability = attrKey;
273 newCapability->status = getUpdateVal(conf);
275 newAction->listOfCapability.push_back(newCapability);
276 newActionSet->listOfAction.push_back(newAction);
279 // Request to create a new action set by using the above actionSet
280 g_groupmanager->addActionSet(resource, newActionSet,
282 void(const HeaderOptions& headerOptions,
283 const OCRepresentation& rep, const int eCode) >(
284 std::bind(&ThingsConfiguration::onCreateActionSet, this,
285 std::placeholders::_1, std::placeholders::_2,
286 std::placeholders::_3, conf)));
292 void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
293 const OCRepresentation& rep, const int eCode, std::string conf)
295 if (eCode != OC_STACK_OK)
297 std::cout << "onGet Response error: " << eCode << std::endl;
298 getCallback(conf)(headerOptions, rep, eCode);
302 std::cout << "GET request was successful" << std::endl;
303 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
305 std::shared_ptr< OCResource > resource, tempResource;
306 std::vector < std::shared_ptr< OCResource > > p_resources;
307 std::vector < std::string > m_if;
308 std::string uri = getUriByConfigurationName(conf);
313 if (uri == "/factoryset" || uri == "/factoryset/oic/con")
314 m_if.push_back(BATCH_INTERFACE);
316 m_if.push_back(DEFAULT_INTERFACE);
318 std::vector < OCRepresentation > children = rep.getChildren();
319 for (auto oit = children.begin(); oit != children.end(); ++oit)
321 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
323 // Using a host address and child URIs, we can dynamically create resource objects.
324 // Note that the child resources have not found before, we have no resource objects.
325 // For this reason, we create the resource objects.
327 std::string host = getHostFromURI(oit->getUri());
329 tempResource = OCPlatform::constructResourceObject(host, uri, OC_IPV4, true,
330 oit->getResourceTypes(), m_if);
332 p_resources.push_back(tempResource);
335 // Send GET messages to the child resources in turn.
336 for (unsigned int i = 0; i < p_resources.size(); ++i)
338 resource = p_resources.at(i);
344 resource->get(test, getCallback(conf));
346 catch (OCException& e)
348 std::cout << e.reason() << std::endl;
355 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
356 const OCRepresentation& rep, const int eCode, std::string conf)
358 if (eCode != OC_STACK_OK)
360 std::cout << "onPut Response error: " << eCode << std::endl;
361 getCallback(conf)(headerOptions, rep, eCode);
365 std::cout << "PUT request was successful" << std::endl;
367 std::shared_ptr < OCResource > resource = getResource(conf);
370 // Now, it is time to execute the action set.
371 g_groupmanager->executeActionSet(resource, conf,
373 void(const HeaderOptions& headerOptions,
374 const OCRepresentation& rep, const int eCode) >(
375 std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
376 std::placeholders::_1, std::placeholders::_2,
377 std::placeholders::_3, conf)));
381 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
382 const OCRepresentation& rep, const int eCode, std::string conf)
384 if (eCode != OC_STACK_OK)
386 std::cout << "onPut Response error: " << eCode << std::endl;
387 getCallback(conf)(headerOptions, rep, eCode);
391 std::cout << "PUT request was successful" << std::endl;
393 getCallback(conf)(headerOptions, rep, eCode);
396 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
399 for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
401 if (resource->getResourceTypes().at(i).find(".resourceset", 0) != std::string::npos)
408 bool ThingsConfiguration::hasBatchInterface(std::shared_ptr< OCResource > resource)
410 for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
412 if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
419 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
420 const int eCode, std::string conf)
422 if (eCode != OC_STACK_OK)
424 std::cout << "onGet Response error: " << eCode << std::endl;
425 getCallback(conf)(headerOptions, rep, eCode);
429 std::cout << "Get request was successful" << std::endl;
431 getCallback(conf)(headerOptions, rep, eCode);
434 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
435 const int eCode, std::string conf)
437 if (eCode != OC_STACK_OK)
439 std::cout << "onPut Response error: " << eCode << std::endl;
440 getCallback(conf)(headerOptions, rep, eCode);
444 std::cout << "PUT request was successful" << std::endl;
446 getCallback(conf)(headerOptions, rep, eCode);
449 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
450 std::map< ConfigurationName, ConfigurationValue > configurations,
451 ConfigurationCallback callback)
453 // For M2, # of configurations is 1
454 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
455 if (configurations.size() == 0)
457 std::cout << "# of request configuration is 0" << std::endl;
458 return OC_STACK_ERROR;
463 std::cout << "resource is NULL\n";
464 return OC_STACK_ERROR;
467 std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
468 std::string conf = it->first; // configuration name
469 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
471 // Check the request queue if a previous request is still left. If so, remove it.
472 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
473 configurationRequestTable.find(conf);
474 if (iter != configurationRequestTable.end())
475 configurationRequestTable.erase(iter);
477 // Create new request entry stored in the queue
478 ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
479 configurationRequestTable.insert(std::make_pair(conf, newCallback));
481 OCRepresentation rep;
482 QueryParamsMap query;
483 if (isSimpleResource(resource))
485 // This resource does not need to use a group manager. Just send a PUT message
486 rep.setValue(conf, getUpdateVal(conf));
487 return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
489 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
491 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
492 std::placeholders::_2, std::placeholders::_3, conf)));
496 // This resource is a collection resource which uses group manager functionalities.
497 // First, delete an existing action set of which name is same as a current action set
498 // name. As of now, the name is determined by "Configuration Name" which a user just
500 return g_groupmanager->deleteActionSet(resource, conf,
502 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
504 std::bind(&ThingsConfiguration::onDeleteActionSet, this,
505 std::placeholders::_1, std::placeholders::_2,
506 std::placeholders::_3, conf)));
510 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
511 std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
513 // For M2, # of configurations is 1
514 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
515 if (configurations.size() == 0)
517 std::cout << "# of request configuration is 0" << std::endl;
518 return OC_STACK_ERROR;
522 std::cout << "resource is NULL\n";
523 return OC_STACK_ERROR;
526 std::vector< ConfigurationName >::iterator it = configurations.begin();
527 std::string conf = (*it); // configuration name
528 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
530 // Check the request queue if a previous request is still left. If so, remove it.
531 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
532 configurationRequestTable.find(conf);
533 if (iter != configurationRequestTable.end())
534 configurationRequestTable.erase(iter);
536 // Create new request entry stored in the queue
537 ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
538 configurationRequestTable.insert(std::make_pair(conf, newCallback));
540 QueryParamsMap query;
541 OCRepresentation rep;
543 if (isSimpleResource(resource))
545 // This resource is a simple resource. Just send a PUT message
546 std::string m_if = DEFAULT_INTERFACE;
548 if (hasBatchInterface(resource))
549 m_if = BATCH_INTERFACE;
551 return resource->get(resource->getResourceTypes().at(0), m_if, query,
553 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
555 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
556 std::placeholders::_2, std::placeholders::_3, conf)));
560 // This resource is a collection resource. On the contrary of a update, it does not use
561 // group manager functionality. It just acquires child resource's URI and send GET
562 // massages to the child resources in turn.
563 // First, request the child resources's URI.
564 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
566 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
568 std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
569 std::placeholders::_1, std::placeholders::_2,
570 std::placeholders::_3, conf)));
575 // callback handler on GET request
576 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions,
577 const OCRepresentation& rep, const int eCode)
579 if (eCode != OC_STACK_OK)
581 std::cout << "onGET Response error: " << eCode << std::endl;
582 g_bootstrapCallback(headerOptions, rep, eCode);
586 g_bootstrapCallback(headerOptions, rep, eCode);
589 void ThingsConfiguration::onFoundBootstrapServer(
590 std::vector< std::shared_ptr< OCResource > > resources)
592 std::string resourceURI;
593 std::string hostAddress;
597 // Do some operations with resource object.
598 for (unsigned int i = 0; i < resources.size(); ++i)
600 std::shared_ptr < OCResource > resource = resources.at(i);
603 { // Request configuration resources
605 std::cout << "Getting bootstrap server representation on: " << DEFAULT_INTERFACE
608 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(),
609 &onGetBootstrapInformation);
614 // Resource is invalid
615 std::cout << "Resource is invalid" << std::endl;
620 catch (std::exception& e)
626 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
629 return OC_STACK_ERROR;
631 g_bootstrapCallback = callback;
633 // Find bootstrap server.
634 std::vector < std::string > type;
635 type.push_back("bootstrap");
637 std::cout << "Finding Bootstrap Server resource... " << std::endl;
638 return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);