Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / things-manager / sdk / src / ThingsDiagnostics.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 /**
22  * @file
23  *
24  */
25
26 #include <OCApi.h>
27 #include <OCPlatform.h>
28 #include <cstdlib>
29
30 #include "ThingsDiagnostics.h"
31
32 using namespace OC;
33
34 namespace OIC
35 {
36     std::map< std::string, DiagnosticsRequestEntry > diagnosticsRequestTable;
37     ThingsDiagnostics* ThingsDiagnostics::thingsDiagnosticsInstance = NULL;
38
39     DiagnosticsRequestEntry::DiagnosticsRequestEntry(std::string ID, DiagnosticsCallback callback,
40                 std::shared_ptr< OCResource > resource, std::string updateVal)
41     {
42         m_ID = ID;
43         m_callback = callback;
44         m_resource = resource;
45         m_updateVal = updateVal;
46     }
47
48     DiagnosticsUnitInfo::DiagnosticsUnitInfo(std::string name,
49                                             std::string attribute,
50                                             std::string uri)
51     {
52         m_name = name;
53         m_attribute = attribute;
54         m_uri = uri;
55     }
56
57     std::string DiagnosticsUnitInfo::getJSON()
58     {
59         std::string res;
60
61         res = "{\"name\":\"" + m_name + "\",\"attribute\":\"" + m_attribute + "\"}";
62
63         return res;
64     }
65
66     ThingsDiagnostics::ThingsDiagnostics()
67     {
68         DiagnosticsUnitInfo unit[] =
69                 {
70                 { "rb", "Reboot", "/oic/diag"},
71                 { "ssc", "StartStatCollection", "/oic/diag"},
72                 { "fr", "Factory Reset", "/oic/diag" } };
73
74         for (int i = 0; i < NUMDIAGUNIT; i++)
75             DiagnosticsUnitTable.push_back(unit[i]);
76     }
77
78     ThingsDiagnostics::~ThingsDiagnostics()
79     {
80     }
81
82     void ThingsDiagnostics::setGroupManager(GroupManager *groupmanager)
83     {
84         g_groupmanager = groupmanager;
85     }
86
87     ThingsDiagnostics* ThingsDiagnostics::getInstance()
88     {
89         if (thingsDiagnosticsInstance == NULL)
90         {
91             thingsDiagnosticsInstance = new ThingsDiagnostics();
92         }
93         return thingsDiagnosticsInstance;
94     }
95
96     void ThingsDiagnostics::deleteInstance()
97     {
98         if (thingsDiagnosticsInstance)
99         {
100             delete thingsDiagnosticsInstance;
101             thingsDiagnosticsInstance = NULL;
102         }
103     }
104
105     std::string ThingsDiagnostics::getAttributeByDiagnosticsName(DiagnosticsName name)
106     {
107         for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
108         {
109             if ((*it).m_name == name)
110                 return (*it).m_attribute;
111         }
112
113         return "";
114     }
115
116     std::string ThingsDiagnostics::getUriByDiagnosticsName(DiagnosticsName name)
117     {
118         for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
119         {
120             if ((*it).m_name == name)
121                 return (*it).m_uri;
122         }
123
124         return "";
125     }
126
127     std::string ThingsDiagnostics::getUpdateVal(std::string diag)
128     {
129         std::map< std::string, DiagnosticsRequestEntry >::iterator it =
130                 diagnosticsRequestTable.find(diag);
131
132         if (it == diagnosticsRequestTable.end())
133             return NULL;
134         else
135             return it->second.m_updateVal;
136
137     }
138     std::shared_ptr< OCResource > ThingsDiagnostics::getResource(std::string diag)
139     {
140         std::map< std::string, DiagnosticsRequestEntry >::iterator it =
141                 diagnosticsRequestTable.find(diag);
142
143         if (it == diagnosticsRequestTable.end())
144             return NULL;
145         else
146             return it->second.m_resource;
147     }
148
149     DiagnosticsCallback ThingsDiagnostics::getCallback(std::string diag)
150     {
151         std::map< std::string, DiagnosticsRequestEntry >::iterator it =
152                 diagnosticsRequestTable.find(diag);
153
154         if (it == diagnosticsRequestTable.end())
155             return NULL;
156         else
157             return it->second.m_callback;
158     }
159
160     std::string ThingsDiagnostics::getHostFromURI(std::string oldUri)
161     {
162         size_t f;
163         std::string newUri;
164
165         if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
166             newUri = oldUri.replace(f, oldUri.size(), "");
167         else if ((f = oldUri.find("/oic/")) != string::npos)
168             newUri = oldUri.replace(f, oldUri.size(), "");
169
170         return newUri;
171     }
172
173     std::string ThingsDiagnostics::getListOfSupportedDiagnosticsUnits()
174     {
175         std::string res;
176
177         res = "{\"Diagnostics Units\":[";
178
179         auto it = DiagnosticsUnitTable.begin();
180         while (1)
181         {
182             res = res + (*it).getJSON();
183             it++;
184
185             if (it == DiagnosticsUnitTable.end())
186                 break;
187             else
188                 res += ",";
189         }
190
191         res += "]}";
192
193         return res;
194     }
195
196     void ThingsDiagnostics::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
197             const OCRepresentation& rep, const int eCode, std::string diag)
198     {
199         if (eCode != OC_STACK_OK)
200         {
201             std::cout << "onGet Response error: " << eCode << std::endl;
202             getCallback(diag)(headerOptions, rep, eCode);
203             return ;
204         }
205
206         std::cout << "GET request was successful" << std::endl;
207
208         std::cout << "\tResource URI: " << rep.getUri() << std::endl;
209
210         std::vector < OCRepresentation > children = rep.getChildren();
211         for (auto oit = children.begin(); oit != children.end(); ++oit)
212         {
213             std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
214         }
215
216         // Get information by using diagnostics name(diag)
217         std::shared_ptr < OCResource > resource = getResource(diag);
218         std::string actionstring = diag;
219         std::string uri = getUriByDiagnosticsName(diag);
220         std::string attrKey = diag;
221
222         if (uri == "")
223             return;
224
225         if (resource)
226         {
227             // In this nest, we create a new action set of which name is the dignostics name.
228             // Required information consists of a host address, URI, attribute key, and
229             // attribute value.
230             ActionSet *newActionSet = new ActionSet();
231             newActionSet->actionsetName = diag;
232
233             for (auto oit = children.begin(); oit != children.end(); ++oit)
234             {
235                 Action *newAction = new Action();
236
237                 // oit->getUri() includes a host address as well as URI.
238                 // We should split these to each other and only use the host address to create
239                 // a child resource's URI. Note that the collection resource and its child
240                 // resource are located in same host.
241                 newAction->target = getHostFromURI(oit->getUri()) + uri;
242
243                 Capability *newCapability = new Capability();
244                 newCapability->capability = attrKey;
245                 newCapability->status = getUpdateVal(diag);
246
247                 newAction->listOfCapability.push_back(newCapability);
248                 newActionSet->listOfAction.push_back(newAction);
249             }
250
251             // Request to create a new action set by using the above actionSet
252             g_groupmanager->addActionSet(resource, newActionSet,
253                     std::function<
254                             void(const HeaderOptions& headerOptions,
255                                     const OCRepresentation& rep, const int eCode) >(
256                             std::bind(&ThingsDiagnostics::onCreateActionSet, this,
257                                     std::placeholders::_1, std::placeholders::_2,
258                                     std::placeholders::_3, diag)));
259
260             delete(newActionSet);
261
262         }
263     }
264
265     void ThingsDiagnostics::onCreateActionSet(const HeaderOptions& headerOptions,
266             const OCRepresentation& rep, const int eCode, std::string diag)
267     {
268         if (eCode != OC_STACK_OK)
269         {
270             std::cout << "onPut Response error: " << eCode << std::endl;
271             getCallback(diag)(headerOptions, rep, eCode);
272             return ;
273         }
274
275         std::cout << "PUT request was successful" << std::endl;
276
277         std::shared_ptr < OCResource > resource = getResource(diag);
278         if (resource)
279         {
280             // Now, it is time to execute the action set.
281             g_groupmanager->executeActionSet(resource, diag,
282                     std::function<
283                             void(const HeaderOptions& headerOptions,
284                                     const OCRepresentation& rep, const int eCode) >(
285                             std::bind(&ThingsDiagnostics::onExecuteForGroupAction, this,
286                                     std::placeholders::_1, std::placeholders::_2,
287                                     std::placeholders::_3, diag)));
288         }
289     }
290
291     void ThingsDiagnostics::onExecuteForGroupAction(const HeaderOptions& headerOptions,
292             const OCRepresentation& rep, const int eCode, std::string diag)
293     {
294         if (eCode != OC_STACK_OK)
295         {
296             std::cout << "onPut Response error: " << eCode << std::endl;
297             getCallback(diag)(headerOptions, rep, eCode);
298             return ;
299         }
300
301         std::cout << "PUT request was successful" << std::endl;
302         getCallback(diag)(headerOptions, rep, eCode);
303
304         // Delete the created actionset
305         std::shared_ptr < OCResource > resource = getResource(diag);
306         if (resource)
307         {
308             g_groupmanager->deleteActionSet(resource, diag,
309                     std::function<
310                             void(const HeaderOptions& headerOptions,
311                                     const OCRepresentation& rep, const int eCode) >(
312                             std::bind(&ThingsDiagnostics::onDeleteGroupAction, this,
313                                     std::placeholders::_1, std::placeholders::_2,
314                                     std::placeholders::_3, diag)));
315         }
316     }
317
318     void ThingsDiagnostics::onDeleteGroupAction(const HeaderOptions& headerOptions,
319             const OCRepresentation& rep, const int eCode, std::string diag)
320     {
321         if (eCode != OC_STACK_OK)
322         {
323             std::cout << "Delete actionset returned with error: " << eCode << diag << std::endl;
324             return;
325         }
326
327         std::cout << "Deleted the actionset created!" << diag<< std::endl;
328     }
329
330     void ThingsDiagnostics::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
331             const int eCode, std::string diag)
332     {
333         if (eCode != OC_STACK_OK)
334         {
335             std::cout << "onPut Response error: " << eCode << std::endl;
336             getCallback(diag)(headerOptions, rep, eCode);
337             return ;
338         }
339
340         std::cout << "PUT request was successful" << std::endl;
341
342         getCallback(diag)(headerOptions, rep, eCode);
343
344     }
345
346     bool ThingsDiagnostics::isSimpleResource(std::shared_ptr< OCResource > resource)
347     {
348         for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
349         {
350             if (resource->getResourceTypes().at(0).find(".resourceset", 0) != std::string::npos)
351                 return false;
352         }
353
354         return true;
355     }
356
357     OCStackResult ThingsDiagnostics::reboot(std::shared_ptr< OCResource > resource,
358             DiagnosticsCallback callback)
359     {
360         if (!resource)
361         {
362             std::cout << "resource is NULL\n";
363             return OC_STACK_ERROR;
364         }
365
366         std::string diag = "rb";
367
368         // Check the request queue if a previous request is still left. If so, remove it.
369         std::map< std::string, DiagnosticsRequestEntry >::iterator iter =
370                 diagnosticsRequestTable.find(diag);
371         if (iter != diagnosticsRequestTable.end())
372             diagnosticsRequestTable.erase(iter);
373
374         // Create new request entry stored in the queue
375         DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
376         diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
377
378         QueryParamsMap query;
379         OCRepresentation rep;
380
381         if (isSimpleResource(resource))
382         {
383             // This resource is a simple resource. Just send a PUT message
384             OCRepresentation rep;
385             rep.setValue < std::string > (diag, "true");
386
387             return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
388                     std::function<
389                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
390                                     const int eCode) >(
391                             std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
392                                     std::placeholders::_2, std::placeholders::_3, diag)));
393         }
394         else
395         {
396             // This resource is a collection resource. It just acquires child resource's URI and
397             // send GET massages to the child resources in turn.
398             // First, request the child resources's URI.
399             // TODO: Add a deletion of actionset
400             return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
401                     std::function<
402                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
403                                     const int eCode) >(
404                             std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
405                                     std::placeholders::_1, std::placeholders::_2,
406                                     std::placeholders::_3, diag)));
407         }
408     }
409
410     OCStackResult ThingsDiagnostics::factoryReset(std::shared_ptr< OCResource > resource,
411             DiagnosticsCallback callback)
412     {
413         if (!resource)
414         {
415             std::cout << "resource is NULL\n";
416             return OC_STACK_ERROR;
417         }
418
419         std::string diag = "fr";
420
421         // Check the request queue if a previous request is still left. If so, remove it.
422         std::map< std::string, DiagnosticsRequestEntry >::iterator iter =
423                 diagnosticsRequestTable.find(diag);
424         if (iter != diagnosticsRequestTable.end())
425             diagnosticsRequestTable.erase(iter);
426
427         // Create new request entry stored in the queue
428         DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
429         diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
430
431         QueryParamsMap query;
432         OCRepresentation rep;
433
434         if (isSimpleResource(resource))
435         {
436             // This resource is a simple resource. Just send a PUT message
437             OCRepresentation rep;
438             rep.setValue < std::string > ("value", "true");
439
440             return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
441                     std::function<
442                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
443                                     const int eCode) >(
444                             std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
445                                     std::placeholders::_2, std::placeholders::_3, diag)));
446         }
447         else
448         {
449             // This resource is a collection resource. It just acquires child resource's URI and
450             // send GET massages to the child resources in turn.
451             // First, request the child resources's URI.
452             // TODO: Add a deletion of actionset
453             return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
454                     std::function<
455                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
456                                     const int eCode) >(
457                             std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
458                                     std::placeholders::_1, std::placeholders::_2,
459                                     std::placeholders::_3, diag)));
460         }
461     }
462 }
463