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 { "n", "Device Name", "/oic/con"},
77 { "loc", "Location", "/oic/con"},
78 { "locn", "Location Name", "/oic/con"},
79 { "r", "Region", "/oic/con" },
80 { "c","Currency", "/oic/con" } };
82 for (int i = 0; i < NUMCONFUNIT; i++)
83 ConfigurationUnitTable.push_back(unit[i]);
86 ThingsConfiguration::~ThingsConfiguration(void){}
88 void ThingsConfiguration::setGroupManager(GroupManager *groupmanager)
90 g_groupmanager = groupmanager;
93 ThingsConfiguration* ThingsConfiguration::getInstance()
95 if (thingsConfigurationInstance == NULL)
97 thingsConfigurationInstance = new ThingsConfiguration();
99 return thingsConfigurationInstance;
102 void ThingsConfiguration::deleteInstance()
104 if (thingsConfigurationInstance)
106 delete thingsConfigurationInstance;
107 thingsConfigurationInstance = NULL;
111 std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
113 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
115 if ((*it).m_name == name)
116 return (*it).m_attribute;
122 std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
124 for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
126 if ((*it).m_name == name)
133 std::string ThingsConfiguration::getUpdateVal(std::string conf)
135 std::map< std::string, ConfigurationRequestEntry >::iterator it =
136 configurationRequestTable.find(conf);
138 if (it == configurationRequestTable.end())
141 return it->second.m_updateVal;
144 std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
146 std::map< std::string, ConfigurationRequestEntry >::iterator it =
147 configurationRequestTable.find(conf);
149 if (it == configurationRequestTable.end())
152 return it->second.m_resource;
155 ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
157 std::map< std::string, ConfigurationRequestEntry >::iterator it =
158 configurationRequestTable.find(conf);
160 if (it == configurationRequestTable.end())
163 return it->second.m_callback;
166 std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
170 res = "{\"Configuration Units\":[";
172 auto it = ConfigurationUnitTable.begin();
175 res = res + (*it).getJSON();
178 if (it == ConfigurationUnitTable.end())
189 std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
194 if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
195 newUri = oldUri.replace(f, oldUri.size(), "");
196 else if ((f = oldUri.find("/oic/")) != string::npos)
197 newUri = oldUri.replace(f, oldUri.size(), "");
202 void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
203 const OCRepresentation& rep, const int eCode, std::string conf)
205 std::shared_ptr < OCResource > resource = getResource(conf);
209 QueryParamsMap query;
211 // After deletion of the left action set, find target child resource's URIs by sending
212 // GET message. Note that, this resource is surely a collection resource which has child
214 resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
216 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
218 std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
219 std::placeholders::_1, std::placeholders::_2,
220 std::placeholders::_3, conf)));
225 void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
226 const OCRepresentation& rep, const int eCode, std::string conf)
228 if (eCode != OC_STACK_OK)
230 std::cout << "onPut Response error: " << eCode << std::endl;
231 getCallback(conf)(headerOptions, rep, eCode);
235 std::cout << "GET request was successful" << std::endl;
237 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
239 std::vector < OCRepresentation > children = rep.getChildren();
240 for (auto oit = children.begin(); oit != children.end(); ++oit)
242 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
245 // Get information by using configuration name(conf)
246 std::shared_ptr < OCResource > resource = getResource(conf);
247 std::string actionstring = conf;
248 std::string uri = getUriByConfigurationName(conf);
249 std::string attrKey = conf;
256 // In this nest, we create a new action set of which name is the configuration name.
257 // Required information consists of a host address, URI, attribute key, and
259 ActionSet *newActionSet = new ActionSet();
260 newActionSet->actionsetName = conf;
262 for (auto oit = children.begin(); oit != children.end(); ++oit)
264 Action *newAction = new Action();
266 // oit->getUri() includes a host address as well as URI.
267 // We should split these to each other and only use the host address to create
268 // a child resource's URI. Note that the collection resource and its child
269 // resource are located in same host.
270 newAction->target = getHostFromURI(oit->getUri()) + uri;
272 Capability *newCapability = new Capability();
273 newCapability->capability = attrKey;
274 newCapability->status = getUpdateVal(conf);
276 newAction->listOfCapability.push_back(newCapability);
277 newActionSet->listOfAction.push_back(newAction);
280 // Request to create a new action set by using the above actionSet
281 g_groupmanager->addActionSet(resource, newActionSet,
283 void(const HeaderOptions& headerOptions,
284 const OCRepresentation& rep, const int eCode) >(
285 std::bind(&ThingsConfiguration::onCreateActionSet, this,
286 std::placeholders::_1, std::placeholders::_2,
287 std::placeholders::_3, conf)));
289 delete(newActionSet);
293 void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
294 const OCRepresentation& rep, const int eCode, std::string conf)
296 if (eCode != OC_STACK_OK)
298 std::cout << "onGet Response error: " << eCode << std::endl;
299 getCallback(conf)(headerOptions, rep, eCode);
303 std::cout << "GET request was successful" << std::endl;
304 std::cout << "\tResource URI: " << rep.getUri() << std::endl;
306 std::shared_ptr< OCResource > resource, tempResource;
307 std::vector < std::shared_ptr< OCResource > > p_resources;
308 std::vector < std::string > m_if;
309 std::string uri = getUriByConfigurationName(conf);
314 if (uri == "/factoryset" || uri == "/factoryset/oic/con")
315 m_if.push_back(BATCH_INTERFACE);
317 m_if.push_back(DEFAULT_INTERFACE);
319 std::vector < OCRepresentation > children = rep.getChildren();
320 for (auto oit = children.begin(); oit != children.end(); ++oit)
322 std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
324 // Using a host address and child URIs, we can dynamically create resource objects.
325 // Note that the child resources have not found before, we have no resource objects.
326 // For this reason, we create the resource objects.
328 std::string host = getHostFromURI(oit->getUri());
330 tempResource = OCPlatform::constructResourceObject(host, uri, CT_ADAPTER_IP, true,
331 oit->getResourceTypes(), m_if);
333 p_resources.push_back(tempResource);
336 // Send GET messages to the child resources in turn.
337 for (unsigned int i = 0; i < p_resources.size(); ++i)
339 resource = p_resources.at(i);
345 resource->get(test, getCallback(conf));
347 catch (OCException& e)
349 std::cout << e.reason() << std::endl;
356 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
357 const OCRepresentation& rep, const int eCode, std::string conf)
359 if (eCode != OC_STACK_OK)
361 std::cout << "onPut Response error: " << eCode << std::endl;
362 getCallback(conf)(headerOptions, rep, eCode);
366 std::cout << "PUT request was successful" << std::endl;
368 std::shared_ptr < OCResource > resource = getResource(conf);
371 // Now, it is time to execute the action set.
372 g_groupmanager->executeActionSet(resource, conf,
374 void(const HeaderOptions& headerOptions,
375 const OCRepresentation& rep, const int eCode) >(
376 std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
377 std::placeholders::_1, std::placeholders::_2,
378 std::placeholders::_3, conf)));
382 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
383 const OCRepresentation& rep, const int eCode, std::string conf)
385 if (eCode != OC_STACK_OK)
387 std::cout << "onPut Response error: " << eCode << std::endl;
388 getCallback(conf)(headerOptions, rep, eCode);
392 std::cout << "PUT request was successful" << std::endl;
394 getCallback(conf)(headerOptions, rep, eCode);
397 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
400 for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
402 if (resource->getResourceTypes().at(i).find(".resourceset", 0) != std::string::npos)
409 bool ThingsConfiguration::hasBatchInterface(std::shared_ptr< OCResource > resource)
411 for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
413 if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
420 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
421 const int eCode, std::string conf)
423 if (eCode != OC_STACK_OK)
425 std::cout << "onGet Response error: " << eCode << std::endl;
426 getCallback(conf)(headerOptions, rep, eCode);
430 std::cout << "Get request was successful" << std::endl;
432 getCallback(conf)(headerOptions, rep, eCode);
435 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
436 const int eCode, std::string conf)
438 if (eCode != OC_STACK_OK)
440 std::cout << "onPut Response error: " << eCode << std::endl;
441 getCallback(conf)(headerOptions, rep, eCode);
445 std::cout << "PUT request was successful" << std::endl;
447 getCallback(conf)(headerOptions, rep, eCode);
450 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
451 std::map< ConfigurationName, ConfigurationValue > configurations,
452 ConfigurationCallback callback)
454 // For M2, # of configurations is 1
455 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
456 if (configurations.size() == 0)
458 std::cout << "# of request configuration is 0" << std::endl;
459 return OC_STACK_ERROR;
464 std::cout << "resource is NULL\n";
465 return OC_STACK_ERROR;
468 std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
469 std::string conf = it->first; // configuration name
470 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
472 // Check the request queue if a previous request is still left. If so, remove it.
473 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
474 configurationRequestTable.find(conf);
475 if (iter != configurationRequestTable.end())
476 configurationRequestTable.erase(iter);
478 // Create new request entry stored in the queue
479 ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
480 configurationRequestTable.insert(std::make_pair(conf, newCallback));
482 OCRepresentation rep;
483 QueryParamsMap query;
484 if (isSimpleResource(resource))
486 // This resource does not need to use a group manager. Just send a PUT message
487 rep.setValue(conf, getUpdateVal(conf));
488 return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
490 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
492 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
493 std::placeholders::_2, std::placeholders::_3, conf)));
497 // This resource is a collection resource which uses group manager functionalities.
498 // First, delete an existing action set of which name is same as a current action set
499 // name. As of now, the name is determined by "Configuration Name" which a user just
501 return g_groupmanager->deleteActionSet(resource, conf,
503 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
505 std::bind(&ThingsConfiguration::onDeleteActionSet, this,
506 std::placeholders::_1, std::placeholders::_2,
507 std::placeholders::_3, conf)));
511 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
512 std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
514 // For M2, # of configurations is 1
515 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
516 if (configurations.size() == 0)
518 std::cout << "# of request configuration is 0" << std::endl;
519 return OC_STACK_ERROR;
523 std::cout << "resource is NULL\n";
524 return OC_STACK_ERROR;
527 std::vector< ConfigurationName >::iterator it = configurations.begin();
528 std::string conf = (*it); // configuration name
529 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
531 // Check the request queue if a previous request is still left. If so, remove it.
532 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
533 configurationRequestTable.find(conf);
534 if (iter != configurationRequestTable.end())
535 configurationRequestTable.erase(iter);
537 // Create new request entry stored in the queue
538 ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
539 configurationRequestTable.insert(std::make_pair(conf, newCallback));
541 QueryParamsMap query;
542 OCRepresentation rep;
544 if (isSimpleResource(resource))
546 // This resource is a simple resource. Just send a PUT message
547 std::string m_if = DEFAULT_INTERFACE;
549 if (hasBatchInterface(resource))
550 m_if = BATCH_INTERFACE;
552 return resource->get(resource->getResourceTypes().at(0), m_if, query,
554 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
556 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
557 std::placeholders::_2, std::placeholders::_3, conf)));
561 // This resource is a collection resource. On the contrary of a update, it does not use
562 // group manager functionality. It just acquires child resource's URI and send GET
563 // massages to the child resources in turn.
564 // First, request the child resources's URI.
565 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
567 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
569 std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
570 std::placeholders::_1, std::placeholders::_2,
571 std::placeholders::_3, conf)));
576 // callback handler on GET request
577 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions,
578 const OCRepresentation& rep, const int eCode)
580 if (eCode != OC_STACK_OK)
582 std::cout << "onGET Response error: " << eCode << std::endl;
583 g_bootstrapCallback(headerOptions, rep, eCode);
587 g_bootstrapCallback(headerOptions, rep, eCode);
590 void ThingsConfiguration::onFoundBootstrapServer(
591 std::vector< std::shared_ptr< OCResource > > resources)
593 std::string resourceURI;
594 std::string hostAddress;
598 // Do some operations with resource object.
599 for (unsigned int i = 0; i < resources.size(); ++i)
601 std::shared_ptr < OCResource > resource = resources.at(i);
604 { // Request configuration resources
606 std::cout << "Getting bootstrap server representation on: " << DEFAULT_INTERFACE
609 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(),
610 &onGetBootstrapInformation);
615 // Resource is invalid
616 std::cout << "Resource is invalid" << std::endl;
621 catch (std::exception& e)
627 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
630 return OC_STACK_ERROR;
632 g_bootstrapCallback = callback;
634 // Find bootstrap server.
635 std::vector < std::string > type;
636 type.push_back("bootstrap");
638 std::cout << "Finding Bootstrap Server resource... " << std::endl;
639 return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);