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"
34 const int SUCCESS_RESPONSE = 0;
37 std::map< std::string, ConfigurationRequestEntry > configurationRequestTable;
39 ThingsConfiguration* ThingsConfiguration::thingsConfigurationInstance = NULL;
41 ConfigurationCallback g_bootstrapCallback;
43 ThingsConfiguration* ThingsConfiguration::getInstance()
45 if (thingsConfigurationInstance == NULL)
47 thingsConfigurationInstance = new ThingsConfiguration();
49 return thingsConfigurationInstance;
52 void ThingsConfiguration::deleteInstance()
54 if (thingsConfigurationInstance)
56 delete thingsConfigurationInstance;
57 thingsConfigurationInstance = NULL;
61 std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
63 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
65 if ((*it).m_name == name)
66 return (*it).m_attribute;
72 std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
74 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
76 if ((*it).m_name == name)
83 std::string ThingsConfiguration::getUpdateVal(std::string conf)
85 std::map< std::string, ConfigurationRequestEntry >::iterator it =
86 configurationRequestTable.find(conf);
88 if (it == configurationRequestTable.end())
91 return it->second.m_updateVal;
94 std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
96 std::map< std::string, ConfigurationRequestEntry >::iterator it =
97 configurationRequestTable.find(conf);
99 if (it == configurationRequestTable.end())
102 return it->second.m_resource;
105 ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
107 std::map< std::string, ConfigurationRequestEntry >::iterator it =
108 configurationRequestTable.find(conf);
110 if (it == configurationRequestTable.end())
113 return it->second.m_callback;
116 std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
120 res = "{\"Configuration Units\":[";
122 auto it = ConfigurationUnitTable.begin();
125 res = res + (*it).getJSON();
128 if (it == ConfigurationUnitTable.end())
139 std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
144 if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
145 newUri = oldUri.replace(f, oldUri.size(), "");
146 else if ((f = oldUri.find("/oic/")) != string::npos)
147 newUri = oldUri.replace(f, oldUri.size(), "");
152 void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
153 const OCRepresentation& rep, const int eCode, std::string conf)
155 std::shared_ptr < OCResource > resource = getResource(conf);
157 std::cout << __func__ << std::endl;
161 QueryParamsMap query;
163 // After deletion of the left action set, find target child resource's URIs by sending
164 // GET message. Note that, this resource is surely a collection resource which has child
166 resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
168 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
170 std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
171 std::placeholders::_1, std::placeholders::_2,
172 std::placeholders::_3, conf)));
178 void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
179 const OCRepresentation& rep, const int eCode, std::string conf)
181 if (eCode == SUCCESS_RESPONSE)
183 std::cout << "GET request was successful" << std::endl;
185 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
187 std::vector < OCRepresentation > children = rep.getChildren();
188 for (auto oit = children.begin(); oit != children.end(); ++oit)
190 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
193 // Get information by using configuration name(conf)
194 std::shared_ptr < OCResource > resource = getResource(conf);
195 std::string actionstring = conf;
196 std::string uri = getUriByConfigurationName(conf);
197 std::string attr = getAttributeByConfigurationName(conf);
204 // In this nest, we create a new action set of which name is the configuration name.
205 // Required information consists of a host address, URI, attribute key, and
207 ActionSet *newActionSet = new ActionSet();
208 newActionSet->actionsetName = conf;
210 for (auto oit = children.begin(); oit != children.end(); ++oit)
212 Action *newAction = new Action();
214 // oit->getUri() includes a host address as well as URI.
215 // We should split these to each other and only use the host address to create
216 // a child resource's URI. Note that the collection resource and its child
217 // resource are located in same host.
218 newAction->target = getHostFromURI(oit->getUri()) + uri;
220 Capability *newCapability = new Capability();
221 newCapability->capability = attr;
222 newCapability->status = getUpdateVal(conf);
224 newAction->listOfCapability.push_back(newCapability);
225 newActionSet->listOfAction.push_back(newAction);
228 // Request to create a new action set by using the above actionSet
229 g_groupmanager->addActionSet(resource, newActionSet,
231 void(const HeaderOptions& headerOptions,
232 const OCRepresentation& rep, const int eCode) >(
233 std::bind(&ThingsConfiguration::onCreateActionSet, this,
234 std::placeholders::_1, std::placeholders::_2,
235 std::placeholders::_3, conf)));
243 std::cout << "onPut Response error: " << eCode << std::endl;
248 void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
249 const OCRepresentation& rep, const int eCode, std::string conf)
251 if (eCode == SUCCESS_RESPONSE)
253 std::cout << "GET request was successful" << std::endl;
254 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
256 std::shared_ptr< OCResource > resource, tempResource;
257 std::vector < std::shared_ptr< OCResource > > p_resources;
258 std::vector < std::string > m_if;
259 std::string uri = getUriByConfigurationName(conf);
264 if (uri == "/oic/con" || uri == "/factoryset" || uri == "/factoryset/oic/con")
265 m_if.push_back(BATCH_INTERFACE);
267 m_if.push_back(DEFAULT_INTERFACE);
269 std::vector < OCRepresentation > children = rep.getChildren();
270 for (auto oit = children.begin(); oit != children.end(); ++oit)
272 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
274 // Using a host address and child URIs, we can dynamically create resource objects.
275 // Note that the child resources have not found before, we have no resource objects.
276 // For this reason, we create the resource objects.
278 std::string host = getHostFromURI(oit->getUri());
280 tempResource = OCPlatform::constructResourceObject(host, uri, OC_WIFI, true,
281 oit->getResourceTypes(), m_if);
283 tempResource = OCPlatform::constructResourceObject(host, uri, true,
284 oit->getResourceTypes(), m_if);
287 p_resources.push_back(tempResource);
290 // Send GET messages to the child resources in turn.
291 for (unsigned int i = 0; i < p_resources.size(); ++i)
293 resource = p_resources.at(i);
298 if (isSimpleResource(resource))
301 resource->get(test, getCallback(conf));
306 resource->get(resource->getResourceTypes().at(0), BATCH_INTERFACE, test,
310 catch (OCException& e)
312 std::cout << e.reason() << std::endl;
320 std::cout << "onPut Response error: " << eCode << std::endl;
325 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
326 const OCRepresentation& rep, const int eCode, std::string conf)
328 if (eCode == SUCCESS_RESPONSE)
330 std::cout << "PUT request was successful" << std::endl;
332 std::shared_ptr < OCResource > resource = getResource(conf);
335 // Now, it is time to execute the action set.
336 g_groupmanager->executeActionSet(resource, conf,
338 void(const HeaderOptions& headerOptions,
339 const OCRepresentation& rep, const int eCode) >(
340 std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
341 std::placeholders::_1, std::placeholders::_2,
342 std::placeholders::_3, conf)));
347 std::cout << "onPut Response error: " << eCode << std::endl;
352 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
353 const OCRepresentation& rep, const int eCode, std::string conf)
355 if (eCode == SUCCESS_RESPONSE)
357 std::cout << "PUT request was successful" << std::endl;
359 getCallback(conf)(headerOptions, rep, eCode);
363 std::cout << "onPut Response error: " << eCode << std::endl;
368 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
371 for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
373 if (resource->getResourceTypes().at(i).find(".resourceset", 0) != std::string::npos)
380 bool ThingsConfiguration::hasBatchInterface(std::shared_ptr< OCResource > resource)
382 for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
384 if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
391 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
392 const int eCode, std::string conf)
394 if (eCode == SUCCESS_RESPONSE)
396 std::cout << "Get request was successful" << std::endl;
398 getCallback(conf)(headerOptions, rep, eCode);
402 std::cout << "onPut Response error: " << eCode << std::endl;
407 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
408 const int eCode, std::string conf)
410 if (eCode == SUCCESS_RESPONSE)
412 std::cout << "PUT request was successful" << std::endl;
415 getCallback(conf)(headerOptions, rep, eCode);
419 std::cout << "onPut Response error: " << eCode << std::endl;
424 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
425 std::map< ConfigurationName, ConfigurationValue > configurations,
426 ConfigurationCallback callback)
428 // For M2, # of configurations is 1
429 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
430 if (configurations.size() == 0)
432 std::cout << "# of request configuration is 0" << std::endl;
433 return OC_STACK_ERROR;
438 std::cout << "resource is NULL\n";
439 return OC_STACK_ERROR;
442 std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
443 std::string conf = it->first; // configuration name
444 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
446 // Check the request queue if a previous request is still left. If so, remove it.
447 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
448 configurationRequestTable.find(conf);
449 if (iter != configurationRequestTable.end())
450 configurationRequestTable.erase(iter);
452 // Create new request entry stored in the queue
453 ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
454 configurationRequestTable.insert(std::make_pair(conf, newCallback));
456 OCRepresentation rep;
457 QueryParamsMap query;
458 if (isSimpleResource(resource))
460 // This resource does not need to use a group manager. Just send a PUT message
461 rep.setValue(getAttributeByConfigurationName(conf), getUpdateVal(conf));
462 return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
464 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
466 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
467 std::placeholders::_2, std::placeholders::_3, conf)));
471 // This resource is a collection resource which uses group manager functionalities.
472 // First, delete an existing action set of which name is same as a current action set
473 // name. As of now, the name is determined by "Configuration Name" which a user just
475 return g_groupmanager->deleteActionSet(resource, conf,
477 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
479 std::bind(&ThingsConfiguration::onDeleteActionSet, this,
480 std::placeholders::_1, std::placeholders::_2,
481 std::placeholders::_3, conf)));
485 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
486 std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
488 // For M2, # of configurations is 1
489 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
490 if (configurations.size() == 0)
492 std::cout << "# of request configuration is 0" << std::endl;
493 return OC_STACK_ERROR;
497 std::cout << "resource is NULL\n";
498 return OC_STACK_ERROR;
501 std::vector< ConfigurationName >::iterator it = configurations.begin();
502 std::string conf = (*it); // configuration name
503 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
505 // Check the request queue if a previous request is still left. If so, remove it.
506 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
507 configurationRequestTable.find(conf);
508 if (iter != configurationRequestTable.end())
509 configurationRequestTable.erase(iter);
511 // Create new request entry stored in the queue
512 ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
513 configurationRequestTable.insert(std::make_pair(conf, newCallback));
515 QueryParamsMap query;
516 OCRepresentation rep;
518 if (isSimpleResource(resource))
520 // This resource is a simple resource. Just send a PUT message
521 std::string m_if = DEFAULT_INTERFACE;
523 if (hasBatchInterface(resource))
524 m_if = BATCH_INTERFACE;
526 return resource->get(resource->getResourceTypes().at(0), m_if, query,
528 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
530 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
531 std::placeholders::_2, std::placeholders::_3, conf)));
535 // This resource is a collection resource. On the contrary of a update, it does not use
536 // group manager functionality. It just acquires child resource's URI and send GET
537 // massages to the child resources in turn.
538 // First, request the child resources's URI.
539 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
541 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
543 std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
544 std::placeholders::_1, std::placeholders::_2,
545 std::placeholders::_3, conf)));
550 // callback handler on GET request
551 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions,
552 const OCRepresentation& rep, const int eCode)
554 if (eCode == SUCCESS_RESPONSE)
556 g_bootstrapCallback(headerOptions, rep, eCode);
561 std::cout << "onGET Response error: " << eCode << std::endl;
566 void ThingsConfiguration::onFoundBootstrapServer(
567 std::vector< std::shared_ptr< OCResource > > resources)
569 std::string resourceURI;
570 std::string hostAddress;
574 // Do some operations with resource object.
575 for (unsigned int i = 0; i < resources.size(); ++i)
577 std::shared_ptr < OCResource > resource = resources.at(i);
580 { // Request configuration resources
582 std::cout << "Getting bootstrap server representation on: " << DEFAULT_INTERFACE
585 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(),
586 &onGetBootstrapInformation);
591 // Resource is invalid
592 std::cout << "Resource is invalid" << std::endl;
597 catch (std::exception& e)
603 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
606 return OC_STACK_ERROR;
608 g_bootstrapCallback = callback;
610 // Find bootstrap server.
611 std::vector < std::string > type;
612 type.push_back("bootstrap");
614 std::cout << "Finding Bootstrap Server resource... " << std::endl;
615 return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);