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());
332 tempResource = OCPlatform::constructResourceObject(host, uri, CT_ADAPTER_IP, true,
333 oit->getResourceTypes(), m_if);
335 p_resources.push_back(tempResource);
336 } catch (std::exception& e)
338 std::cout << "Exception: " << e.what() << std::endl;
342 // Send GET messages to the child resources in turn.
343 for (unsigned int i = 0; i < p_resources.size(); ++i)
345 resource = p_resources.at(i);
351 resource->get(test, getCallback(conf));
353 catch (OCException& e)
355 std::cout << e.reason() << std::endl;
362 void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
363 const OCRepresentation& rep, const int eCode, std::string conf)
365 if (eCode != OC_STACK_OK)
367 std::cout << "onPut Response error: " << eCode << std::endl;
368 getCallback(conf)(headerOptions, rep, eCode);
372 std::cout << "PUT request was successful" << std::endl;
374 std::shared_ptr < OCResource > resource = getResource(conf);
377 // Now, it is time to execute the action set.
378 g_groupmanager->executeActionSet(resource, conf,
380 void(const HeaderOptions& headerOptions,
381 const OCRepresentation& rep, const int eCode) >(
382 std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
383 std::placeholders::_1, std::placeholders::_2,
384 std::placeholders::_3, conf)));
388 void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
389 const OCRepresentation& rep, const int eCode, std::string conf)
391 if (eCode != OC_STACK_OK)
393 std::cout << "onPut Response error: " << eCode << std::endl;
394 getCallback(conf)(headerOptions, rep, eCode);
398 std::cout << "PUT request was successful" << std::endl;
400 getCallback(conf)(headerOptions, rep, eCode);
403 bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
406 for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
408 if (resource->getResourceTypes().at(i).find(".resourceset", 0) != std::string::npos)
415 bool ThingsConfiguration::hasBatchInterface(std::shared_ptr< OCResource > resource)
417 for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
419 if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
426 void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
427 const int eCode, std::string conf)
429 if (eCode != OC_STACK_OK)
431 std::cout << "onGet Response error: " << eCode << std::endl;
432 getCallback(conf)(headerOptions, rep, eCode);
436 std::cout << "Get request was successful" << std::endl;
438 getCallback(conf)(headerOptions, rep, eCode);
441 void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
442 const int eCode, std::string conf)
444 if (eCode != OC_STACK_OK)
446 std::cout << "onPut Response error: " << eCode << std::endl;
447 getCallback(conf)(headerOptions, rep, eCode);
451 std::cout << "PUT request was successful" << std::endl;
453 getCallback(conf)(headerOptions, rep, eCode);
456 OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
457 std::map< ConfigurationName, ConfigurationValue > configurations,
458 ConfigurationCallback callback)
460 // For M2, # of configurations is 1
461 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
462 if (configurations.size() == 0)
464 std::cout << "# of request configuration is 0" << std::endl;
465 return OC_STACK_ERROR;
470 std::cout << "resource is NULL\n";
471 return OC_STACK_ERROR;
474 std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
475 std::string conf = it->first; // configuration name
476 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
478 // Check the request queue if a previous request is still left. If so, remove it.
479 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
480 configurationRequestTable.find(conf);
481 if (iter != configurationRequestTable.end())
482 configurationRequestTable.erase(iter);
484 // Create new request entry stored in the queue
485 ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
486 configurationRequestTable.insert(std::make_pair(conf, newCallback));
488 OCRepresentation rep;
489 QueryParamsMap query;
490 if (isSimpleResource(resource))
492 // This resource does not need to use a group manager. Just send a PUT message
493 rep.setValue(conf, getUpdateVal(conf));
494 return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
496 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
498 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
499 std::placeholders::_2, std::placeholders::_3, conf)));
503 // This resource is a collection resource which uses group manager functionalities.
504 // First, delete an existing action set of which name is same as a current action set
505 // name. As of now, the name is determined by "Configuration Name" which a user just
507 return g_groupmanager->deleteActionSet(resource, conf,
509 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
511 std::bind(&ThingsConfiguration::onDeleteActionSet, this,
512 std::placeholders::_1, std::placeholders::_2,
513 std::placeholders::_3, conf)));
517 OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
518 std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
520 // For M2, # of configurations is 1
521 // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
522 if (configurations.size() == 0)
524 std::cout << "# of request configuration is 0" << std::endl;
525 return OC_STACK_ERROR;
529 std::cout << "resource is NULL\n";
530 return OC_STACK_ERROR;
533 std::vector< ConfigurationName >::iterator it = configurations.begin();
534 std::string conf = (*it); // configuration name
535 std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
537 // Check the request queue if a previous request is still left. If so, remove it.
538 std::map< std::string, ConfigurationRequestEntry >::iterator iter =
539 configurationRequestTable.find(conf);
540 if (iter != configurationRequestTable.end())
541 configurationRequestTable.erase(iter);
543 // Create new request entry stored in the queue
544 ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
545 configurationRequestTable.insert(std::make_pair(conf, newCallback));
547 QueryParamsMap query;
548 OCRepresentation rep;
550 if (isSimpleResource(resource))
552 // This resource is a simple resource. Just send a PUT message
553 std::string m_if = DEFAULT_INTERFACE;
555 if (hasBatchInterface(resource))
556 m_if = BATCH_INTERFACE;
558 return resource->get(resource->getResourceTypes().at(0), m_if, query,
560 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
562 std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
563 std::placeholders::_2, std::placeholders::_3, conf)));
567 // This resource is a collection resource. On the contrary of a update, it does not use
568 // group manager functionality. It just acquires child resource's URI and send GET
569 // massages to the child resources in turn.
570 // First, request the child resources's URI.
571 return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
573 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
575 std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
576 std::placeholders::_1, std::placeholders::_2,
577 std::placeholders::_3, conf)));
582 // callback handler on GET request
583 void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions,
584 const OCRepresentation& rep, const int eCode)
586 if (eCode != OC_STACK_OK)
588 std::cout << "onGET Response error: " << eCode << std::endl;
589 g_bootstrapCallback(headerOptions, rep, eCode);
593 g_bootstrapCallback(headerOptions, rep, eCode);
596 void ThingsConfiguration::onFoundBootstrapServer(
597 std::vector< std::shared_ptr< OCResource > > resources)
599 std::string resourceURI;
600 std::string hostAddress;
604 // Do some operations with resource object.
605 for (unsigned int i = 0; i < resources.size(); ++i)
607 std::shared_ptr < OCResource > resource = resources.at(i);
610 { // Request configuration resources
612 std::cout << "Getting bootstrap server representation on: " << DEFAULT_INTERFACE
615 resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(),
616 &onGetBootstrapInformation);
621 // Resource is invalid
622 std::cout << "Resource is invalid" << std::endl;
627 catch (std::exception& e)
633 OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
636 return OC_STACK_ERROR;
638 g_bootstrapCallback = callback;
640 // Find bootstrap server.
641 std::vector < std::string > type;
642 type.push_back("bootstrap");
644 std::cout << "Finding Bootstrap Server resource... " << std::endl;
645 return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);