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 /// @file ThingsConfiguration.cpp
25 #include <OCPlatform.h>
28 #include "ThingsConfiguration.h"
32 const int SUCCESS_RESPONSE = 0;
35 std::map< std::string, ConfigurationRequestEntry > configurationRequestTable;
37 ThingsConfiguration* ThingsConfiguration::thingsConfigurationInstance = NULL;
39 ConfigurationCallback g_bootstrapCallback;
41 ThingsConfiguration* ThingsConfiguration::getInstance()
43 if (thingsConfigurationInstance == NULL)
45 thingsConfigurationInstance = new ThingsConfiguration();
47 return thingsConfigurationInstance;
50 void ThingsConfiguration::deleteInstance()
52 if (thingsConfigurationInstance)
54 delete thingsConfigurationInstance;
55 thingsConfigurationInstance = NULL;
59 std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
61 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
63 if ((*it).m_name == name)
64 return (*it).m_attribute;
70 std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
72 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
74 if ((*it).m_name == name)
81 std::string ThingsConfiguration::getUpdateVal(std::string conf)
83 std::map< std::string, ConfigurationRequestEntry >::iterator it =
84 configurationRequestTable.find(conf);
86 if (it == configurationRequestTable.end())
89 return it->second.m_updateVal;
92 std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
94 std::map< std::string, ConfigurationRequestEntry >::iterator it =
95 configurationRequestTable.find(conf);
97 if (it == configurationRequestTable.end())
100 return it->second.m_resource;
103 ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
105 std::map< std::string, ConfigurationRequestEntry >::iterator it =
106 configurationRequestTable.find(conf);
108 if (it == configurationRequestTable.end())
111 return it->second.m_callback;
114 std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
118 res = "{\"Configuration Units\":[";
120 auto it = ConfigurationUnitTable.begin();
123 res = res + (*it).getJSON();
126 if (it == ConfigurationUnitTable.end())
137 std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
142 if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
143 newUri = oldUri.replace(f, oldUri.size(), "");
144 else if ((f = oldUri.find("/oic/")) != string::npos)
145 newUri = oldUri.replace(f, oldUri.size(), "");
150 void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
151 const OCRepresentation& rep, const int eCode, std::string conf)
153 std::shared_ptr < OCResource > resource = getResource(conf);
155 std::cout << __func__ << std::endl;
159 QueryParamsMap query;
161 // After deletion of the left action set, find target child resource's URIs by sending GET
162 // message. Note that, this resource is surely a collection resource which has child
164 resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
166 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
168 std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
169 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
176 void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
177 const OCRepresentation& rep, const int eCode, std::string conf)
179 if (eCode == SUCCESS_RESPONSE)
181 std::cout << "GET request was successful" << std::endl;
183 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
185 std::vector < OCRepresentation > children = rep.getChildren();
186 for (auto oit = children.begin(); oit != children.end(); ++oit)
188 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
191 // Get information by using configuration name(conf)
192 std::shared_ptr < OCResource > resource = getResource(conf);
193 std::string actionstring = conf;
194 std::string uri = getUriByConfigurationName(conf);
195 std::string attr = getAttributeByConfigurationName(conf);
202 // In this nest, we create a new action set of which name is the configuration name.
203 // Required information consists of a host address, URI, attribute key, and attribute
205 ActionSet *newActionSet = new ActionSet();
206 newActionSet->actionsetName = conf;
208 for (auto oit = children.begin(); oit != children.end(); ++oit)
210 Action *newAction = new Action();
212 // oit->getUri() includes a host address as well as URI.
213 // We should split these to each other and only use the host address to create
214 // a child resource's URI. Note that the collection resource and its child resource
215 // are located in same host.
216 newAction->target = getHostFromURI(oit->getUri()) + uri;
218 Capability *newCapability = new Capability();
219 newCapability->capability = attr;
220 newCapability->status = getUpdateVal(conf);
222 newAction->listOfCapability.push_back(newCapability);
223 newActionSet->listOfAction.push_back(newAction);
226 // Request to create a new action set by using the above actionSet
227 g_groupmanager->addActionSet(resource, newActionSet,
229 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
231 std::bind(&ThingsConfiguration::onCreateActionSet, this,
232 std::placeholders::_1, std::placeholders::_2,
233 std::placeholders::_3, conf)));
239 std::cout << "onPut Response error: " << eCode << std::endl;
244 void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
245 const OCRepresentation& rep, const int eCode, std::string conf)
247 if (eCode == SUCCESS_RESPONSE)
249 std::cout << "GET request was successful" << std::endl;
250 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
252 std::shared_ptr< OCResource > resource, tempResource;
253 std::vector < std::shared_ptr < OCResource >> p_resources;
254 std::vector < std::string > m_if;
255 std::string uri = getUriByConfigurationName(conf);
260 if (uri == "/oic/con" || uri == "/factoryset" || uri == "/factoryset/oic/con")
261 m_if.push_back(BATCH_INTERFACE);
263 m_if.push_back(DEFAULT_INTERFACE);
265 std::vector < OCRepresentation > children = rep.getChildren();
266 for (auto oit = children.begin(); oit != children.end(); ++oit)
268 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
270 // Using a host address and child URIs, we can dynamically create resource objects.
271 // Note that, the child resources have not found before, we have no resource objects.
272 // For this reason, we create the resource objects.
274 std::string host = getHostFromURI(oit->getUri());
275 tempResource = OCPlatform::constructResourceObject(host, uri, true,
276 oit->getResourceTypes(), m_if);
278 p_resources.push_back(tempResource);
281 // Send GET messages to the child resources in turn.
282 for (unsigned int i = 0; i < p_resources.size(); ++i)
284 resource = p_resources.at(i);
289 if (isSimpleResource(resource))
292 resource->get(test, getCallback(conf));
297 resource->get(resource->getResourceTypes().at(0), BATCH_INTERFACE, test,
301 catch (OCException& e)
303 std::cout << e.reason() << std::endl;
311 std::cout << "onPut Response error: " << eCode << std::endl;
316 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
317 const OCRepresentation& rep, const int eCode, std::string conf)
319 if (eCode == SUCCESS_RESPONSE)
321 std::cout << "PUT request was successful" << std::endl;
323 std::shared_ptr < OCResource > resource = getResource(conf);
326 // Now, it is time to execute the action set.
327 g_groupmanager->executeActionSet(resource, conf,
329 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
331 std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
332 std::placeholders::_1, std::placeholders::_2,
333 std::placeholders::_3, conf)));
338 std::cout << "onPut Response error: " << eCode << std::endl;
343 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
344 const OCRepresentation& rep, const int eCode, std::string conf)
346 if (eCode == SUCCESS_RESPONSE)
348 std::cout << "PUT request was successful" << std::endl;
350 getCallback(conf)(headerOptions, rep, eCode);
354 std::cout << "onPut Response error: " << eCode << std::endl;
359 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
361 for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
363 if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
369 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
370 const int eCode, std::string conf)
372 if (eCode == SUCCESS_RESPONSE)
374 std::cout << "Get request was successful" << std::endl;
376 getCallback(conf)(headerOptions, rep, eCode);
380 std::cout << "onPut Response error: " << eCode << std::endl;
385 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
386 const int eCode, std::string conf)
388 if (eCode == SUCCESS_RESPONSE)
390 std::cout << "PUT request was successful" << std::endl;
393 getCallback(conf)(headerOptions, rep, eCode);
397 std::cout << "onPut Response error: " << eCode << std::endl;
402 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
403 std::map< ConfigurationName, ConfigurationValue > configurations,
404 ConfigurationCallback callback)
406 // For M2, # of configurations is 1
407 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
408 if (configurations.size() == 0)
410 std::cout << "# of request configuration is 0" << std::endl;
411 return OC_STACK_ERROR;
416 std::cout << "resource is NULL\n";
417 return OC_STACK_ERROR;
420 std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
421 std::string conf = it->first; // configuration name
422 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
424 // Check the request queue if a previous request is still left. If so, remove it.
425 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
426 configurationRequestTable.find(conf);
427 if (iter != configurationRequestTable.end())
428 configurationRequestTable.erase(iter);
430 // Create new request entry stored in the queue
431 ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
432 configurationRequestTable.insert(std::make_pair(conf, newCallback));
434 OCRepresentation rep;
435 QueryParamsMap query;
436 if (isSimpleResource(resource))
438 // This resource does not need to use a group manager. Just send a PUT message
439 rep.setValue(getAttributeByConfigurationName(conf), getUpdateVal(conf));
440 return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
442 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
444 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
445 std::placeholders::_2, std::placeholders::_3, conf)));
449 // This resource is a collection resource which uses group manager functionalities.
450 // First, delete an existing action set of which name is same as a current action set name.
451 // As of now, the name is determined by "Configuration Name" which a user just specifies.
452 return g_groupmanager->deleteActionSet(resource, conf,
454 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
456 std::bind(&ThingsConfiguration::onDeleteActionSet, this,
457 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
462 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
463 std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
465 // For M2, # of configurations is 1
466 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
467 if (configurations.size() == 0)
469 std::cout << "# of request configuration is 0" << std::endl;
470 return OC_STACK_ERROR;
474 std::cout << "resource is NULL\n";
475 return OC_STACK_ERROR;
478 std::vector< ConfigurationName >::iterator it = configurations.begin();
479 std::string conf = (*it); // configuration name
480 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
482 // Check the request queue if a previous request is still left. If so, remove it.
483 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
484 configurationRequestTable.find(conf);
485 if (iter != configurationRequestTable.end())
486 configurationRequestTable.erase(iter);
488 // Create new request entry stored in the queue
489 ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
490 configurationRequestTable.insert(std::make_pair(conf, newCallback));
492 QueryParamsMap query;
493 OCRepresentation rep;
495 if (isSimpleResource(resource))
497 // This resource is a simple resource. Just send a PUT message
498 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
500 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
502 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
503 std::placeholders::_2, std::placeholders::_3, conf)));
507 // This resource is a collection resource. On the contrary of a update, it does not use
508 // group manager functionality. It just acquires child resource's URI and send GET massages
509 // to the child resources in turn.
510 // First, request the child resources's URI.
511 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
513 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
515 std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
516 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
522 // callback handler on GET request
523 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
525 if(eCode == SUCCESS_RESPONSE)
527 std::cout << "GET request was successful" << std::endl;
529 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
530 g_bootstrapCallback(headerOptions, rep, eCode);
535 std::cout << "onGET Response error: " << eCode << std::endl;
540 void ThingsConfiguration::onFoundBootstrapServer(std::vector< std::shared_ptr< OCResource > > resources)
542 std::string resourceURI;
543 std::string hostAddress;
547 // Do some operations with resource object.
548 for (unsigned int i = 0; i < resources.size(); ++i)
550 std::shared_ptr < OCResource > resource = resources.at(i);
554 std::cout << "DISCOVERED Resource:" << std::endl;
555 // Get the resource URI
556 resourceURI = resource->uri();
557 std::cout << "\tURI of the resource: " << resourceURI << std::endl;
559 // Get the resource host address
560 hostAddress = resource->host();
561 std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
563 // Get the resource types
564 std::cout << "\tList of resource types: " << std::endl;
565 for (auto &resourceTypes : resource->getResourceTypes())
567 std::cout << "\t\t" << resourceTypes << std::endl;
570 // Get the resource interfaces
571 cout << "\tList of resource interfaces: " << endl;
572 for (auto &resourceInterfaces : resource->getResourceInterfaces())
574 cout << "\t\t" << resourceInterfaces << endl;
577 // Request configuration resources
578 std::cout << "Getting bootstrap server representation on: "<< DEFAULT_INTERFACE << std::endl;
580 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(), &onGetBootstrapInformation);
585 // Resource is invalid
586 std::cout << "Resource is invalid" << std::endl;
591 catch (std::exception& e)
597 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
599 g_bootstrapCallback = callback;
601 // Find bootstrap server.
602 std::vector<std::string> type;
603 type.push_back("bootstrap");
605 std::cout << "Finding Bootstrap Server resource... " << std::endl;
606 return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);