Merge branch 'master' into resource-encapsulation
[platform/upstream/iotivity.git] / service / resource-encapsulation / examples / tizen / RESampleClientApp / src / reclient.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 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 #include "reclient.h"
22
23 #include<iostream>
24 #include "mutex"
25 #include "condition_variable"
26
27 #include "reclientmain.h"
28
29 #include "RCSDiscoveryManager.h"
30 #include "RCSRemoteResourceObject.h"
31 #include "RCSResourceAttributes.h"
32 #include "RCSAddress.h"
33
34 #include "OCPlatform.h"
35
36 # define checkResource nullptr == resource?false:true
37
38 using namespace std;
39 using namespace OC;
40 using namespace OIC::Service;
41
42 constexpr int CORRECT_INPUT = 1;
43 constexpr int INCORRECT_INPUT = 2;
44 constexpr int QUIT_INPUT = 3;
45
46 std::shared_ptr<RCSRemoteResourceObject>  resource;
47
48 const std::string defaultKey = "Temperature";
49 const std::string resourceType = "?rt=core.TemperatureSensor";
50 const std::string targetUri = OC_RSRVD_WELL_KNOWN_URI + resourceType;
51
52 std::mutex mtx;
53 std::condition_variable cond;
54
55 static Evas_Object *log_entry = NULL;
56 static Evas_Object *list = NULL;
57 static Evas_Object *naviframe = NULL;
58
59 typedef struct temperature_popup
60 {
61     Evas_Object *popup;
62     Evas_Object *entry;
63 } temperature_popup_fields;
64
65 // Function to update the log in UI
66 void *updateGroupLog(void *data)
67 {
68     string *log = (string *)data;
69     // Show the log
70     elm_entry_entry_append(log_entry, (*log).c_str());
71     elm_entry_cursor_end_set(log_entry);
72     return NULL;
73 }
74
75 static void onDestroy()
76 {
77     dlog_print(DLOG_INFO, LOG_TAG, "#### Destroy sequence called");
78     resource = nullptr;
79 }
80
81 void onResourceDiscovered(std::shared_ptr<RCSRemoteResourceObject> foundResource)
82 {
83     dlog_print(DLOG_INFO, LOG_TAG, "#### onResourceDiscovered callback");
84
85     std::string resourceURI = foundResource->getUri();
86     std::string hostAddress = foundResource->getAddress();
87
88     dlog_print(DLOG_INFO, LOG_TAG, "#### Resource URI :  %s", resourceURI.c_str());
89     dlog_print(DLOG_INFO, LOG_TAG, "#### Resource Host : %S", hostAddress.c_str());
90
91     string logMessage = "Resource Found <br>";
92     logMessage = logMessage + "URI: " + resourceURI + "<br>";
93     logMessage = logMessage + "Host:" + hostAddress + "<br>";
94     logMessage += "----------------------<br>";
95     dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
96     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
97                                           &logMessage);
98
99     resource = foundResource;
100
101     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))showClientAPIs, NULL);
102     cond.notify_all();
103 }
104
105 void onResourceStateChanged(const ResourceState &resourceState)
106 {
107     dlog_print(DLOG_INFO, LOG_TAG, "#### onResourceStateChanged");
108
109     std::string logMessage = "State changed to : ";
110
111     switch (resourceState)
112     {
113         case ResourceState::NONE:
114             logMessage = logMessage + "NOT_MONITORING <br>";
115             break;
116
117         case ResourceState::ALIVE:
118             logMessage = logMessage + "ALIVE <br>";
119             break;
120
121         case ResourceState::REQUESTED:
122             logMessage = logMessage + "REQUESTED <br>";
123             break;
124
125         case ResourceState::LOST_SIGNAL:
126             logMessage = logMessage + "LOST_SIGNAL <br>";
127             resource = nullptr;
128             break;
129
130         case ResourceState::DESTROYED:
131             logMessage = logMessage + "DESTROYED <br>";
132             break;
133     }
134
135     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
136     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
137                                           &logMessage);
138 }
139
140 void onCacheUpdated(const RCSResourceAttributes &attributes)
141 {
142     dlog_print(DLOG_INFO, LOG_TAG, "#### onCacheUpdated callback");
143
144     string logMessage = "Cache Updated : <br> ";
145
146     if (attributes.empty())
147     {
148         logMessage + logMessage + "Attribute is Empty <br>";
149         return;
150     }
151
152     for (const auto & attr : attributes)
153     {
154         logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
155         logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
156     }
157     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
158     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
159                                           &logMessage);
160 }
161
162 void onRemoteAttributesReceivedCallback(const RCSResourceAttributes &attributes)
163 {
164     dlog_print(DLOG_INFO, LOG_TAG, "#### onRemoteAttributesReceivedCallback callback");
165
166     string logMessage = "Remote Attribute Updated : <br> ";
167
168     if (attributes.empty())
169     {
170         logMessage + logMessage + "Attribute is Empty <br>";
171         return;
172     }
173
174     for (const auto & attr : attributes)
175     {
176         logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
177         logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
178     }
179
180     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
181     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
182                                           &logMessage);
183 }
184
185 static void startMonitoring(void *data, Evas_Object *obj, void *event_info)
186 {
187     string logMessage = "";
188
189     if (checkResource)
190     {
191         if (!resource->isMonitoring())
192         {
193             try
194             {
195                 logMessage = logMessage + "Started Monitoring <br>";
196                 resource->startMonitoring(&onResourceStateChanged);
197             }
198             catch (const BadRequestException &e)
199             {
200                 logMessage = logMessage + "Exception BadRequest<br>";
201                 dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in isMonitoring : %s", e.what());
202             }
203             catch (const InvalidParameterException &e)
204             {
205                 logMessage = logMessage + "Exception Invalid Param<br>";
206                 dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in isMonitoring : %s", e.what());
207             }
208         }
209         else
210         {
211             logMessage = logMessage + "Already Monitoring <br>";
212         }
213     }
214     else
215     {
216         logMessage = logMessage + "No Resource to monitor <br>";
217     }
218
219     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
220     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
221                                           &logMessage);
222 }
223
224 static void stopMonitoring(void *data, Evas_Object *obj, void *event_info)
225 {
226     string logMessage = "";
227
228     if (checkResource)
229     {
230         if (resource->isMonitoring())
231         {
232             resource->stopMonitoring();
233             logMessage = logMessage + "Stopped Monitoring <br>";
234         }
235         else
236         {
237             logMessage = logMessage + "Monitoring not started <br>";
238         }
239     }
240     else
241     {
242         logMessage = logMessage + "NO Resource to stop monitor <br>";
243     }
244
245     dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
246     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
247                                           &logMessage);
248 }
249
250 static void list_selected_cb(void *data, Evas_Object *obj, void *event_info)
251 {
252     Elm_Object_Item *it = (Elm_Object_Item *)event_info;
253     elm_list_item_selected_set(it, EINA_FALSE);
254 }
255
256 static void getAttributeFromRemoteServer(void *data, Evas_Object *obj, void *event_info)
257 {
258     if (checkResource)
259     {
260         resource->getRemoteAttributes(&onRemoteAttributesReceivedCallback);
261     }
262     else
263     {
264         dlog_print(DLOG_INFO, LOG_TAG, "#### No Resource to getAttributeFromRemoteServer...");
265     }
266 }
267
268 static void setAttributeToRemoteServer(int setTemperature)
269 {
270     string key = "Temperature";
271     string logMessage = "";
272
273     RCSResourceAttributes setAttribute;
274     setAttribute[key] = setTemperature;
275
276     if (checkResource)
277     {
278         resource->setRemoteAttributes(setAttribute,
279                                       &onRemoteAttributesReceivedCallback);
280     }
281     else
282     {
283         logMessage = "No Resource to setAttributeToRemoteServer";
284     }
285
286     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
287     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
288                                           &logMessage);
289 }
290
291 static void startCaching(std::function <void (const RCSResourceAttributes &)>cb)
292 {
293     string logMessage = "";
294
295     if (checkResource)
296     {
297         if (!resource->isCaching())
298         {
299             if (cb)
300             {
301                 try
302                 {
303                     logMessage = logMessage + "Caching with callback <br>";
304                     resource->startCaching(&onCacheUpdated);
305                 }
306                 catch (const BadRequestException &e)
307                 {
308                     logMessage = logMessage + "Exception BadRequest<br>";
309                     dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in startCaching : %s", e.what());
310                 }
311
312             }
313             else
314             {
315                 try
316                 {
317                     logMessage = logMessage + "Caching without callback <br>";
318                     resource->startCaching();
319                 }
320                 catch (const BadRequestException &e)
321                 {
322                     logMessage = logMessage + "Exception BadRequest<br>";
323                     dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in startCaching : %s", e.what());
324                 }
325             }
326         }
327         else
328         {
329             logMessage = logMessage + "Caching Already Started <br>";
330         }
331     }
332     else
333     {
334         logMessage = logMessage + "No resource to start Caching <br>";
335     }
336
337     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
338     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
339                                           &logMessage);
340 }
341
342 static void startCachingWithoutCallback(void *data, Evas_Object *obj, void *event_info)
343 {
344     startCaching(nullptr);
345 }
346
347 static void startCachingWithCallback(void *data, Evas_Object *obj, void *event_info)
348 {
349     startCaching(onCacheUpdated);
350 }
351
352 static void getResourceCacheState(void *data, Evas_Object *obj, void *event_info)
353 {
354     string logMessage = "CACHE STATE : ";
355     switch (resource->getCacheState())
356     {
357         case CacheState::READY:
358             logMessage = logMessage + "READY <br>";
359             break;
360
361         case CacheState::UNREADY:
362             logMessage = logMessage + "UNREADY <br>";
363             break;
364
365         case CacheState::LOST_SIGNAL:
366             logMessage = logMessage + "LOST_SIGNAL <br>";
367             break;
368
369         case CacheState::NONE:
370             logMessage = logMessage + "NONE <br>";
371             break;
372
373         default:
374             break;
375     }
376
377     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
378     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
379                                           &logMessage);
380 }
381
382 static void getCachedAttributes(void *data, Evas_Object *obj, void *event_info)
383 {
384     string logMessage = "";
385
386     if (checkResource)
387     {
388         try
389         {
390             if (resource->getCachedAttributes().empty())
391             {
392                 logMessage = "Cached attribute empty<br>";
393             }
394             else
395             {
396                 for (const auto & attr : resource->getCachedAttributes())
397                 {
398                     logMessage = logMessage + "KEY:" + attr.key().c_str() + "<br>";
399                     logMessage = logMessage + "VALUE:" + attr.value().toString().c_str() + "<br>";
400                     dlog_print(DLOG_INFO, LOG_TAG, "#### Cached attributes received ");
401                 }
402             }
403         }
404         catch (const BadRequestException &e)
405         {
406             logMessage = "Exception Received<br>";
407             dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttributes : %s", e.what());
408         }
409     }
410     else
411     {
412         logMessage = logMessage + "No Resource<br>";
413         dlog_print(DLOG_INFO, LOG_TAG, "#### No Resource to getCachedAttributes...");
414     }
415
416     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
417     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
418                                           &logMessage);
419 }
420
421 static void getCachedAttribute(void *data, Evas_Object *obj, void *event_info)
422 {
423     string logMessage = "";
424
425     if (checkResource)
426     {
427         try
428         {
429             logMessage = logMessage + "KEY:" + defaultKey.c_str() + "<br>";
430             int attrValue = resource->getCachedAttribute(defaultKey).get< int >();
431             logMessage = logMessage + "VALUE:" + to_string(attrValue) + "<br>";
432         }
433         catch (const BadRequestException &e)
434         {
435             logMessage = logMessage + "Exception BadRequest<br>";
436             dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttribute : %s", e.what());
437         }
438         catch (const BadGetException &e)
439         {
440             logMessage = logMessage + "Exception BadGet<br>";
441             dlog_print(DLOG_INFO, LOG_TAG, "#### Exception in getCachedAttribute : %s", e.what());
442         }
443     }
444     else
445     {
446         logMessage = logMessage + "No resource<br>";
447     }
448
449     dlog_print(DLOG_INFO, LOG_TAG, "#### %s", logMessage.c_str());
450     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
451                                           &logMessage);
452 }
453
454 static void stopCaching(void *data, Evas_Object *obj, void *event_info)
455 {
456     string logMessage = "";
457
458     if (checkResource)
459     {
460         if (resource->isCaching())
461         {
462             resource->stopCaching();
463             logMessage = logMessage + "Caching stopped <br>";
464         }
465         else
466         {
467             logMessage = logMessage + "Caching not started <br>";
468         }
469     }
470     else
471     {
472         logMessage = logMessage + "No resource found<br>";
473     }
474
475     dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
476     ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
477                                           &logMessage);
478 }
479
480 void discoverResource()
481 {
482     dlog_print(DLOG_INFO, LOG_TAG, "#### Wait 2 seconds until discovered");
483
484     RCSDiscoveryManager::getInstance()->discoverResource(RCSAddress::multicast(), targetUri,
485             &onResourceDiscovered);
486
487     std::unique_lock<std::mutex> lck(mtx);
488     cond.wait_for(lck, std::chrono::seconds(2));
489
490     dlog_print(DLOG_INFO, LOG_TAG, "#### Discovery over");
491 }
492
493 static void
494 popup_cancel_clicked_cb(void *data, Evas_Object *obj, void *event_info)
495 {
496     temperature_popup_fields *popup_fields = (temperature_popup_fields *)data;
497     evas_object_del(popup_fields->popup);
498     free(popup_fields);
499 }
500
501 static void
502 popup_set_clicked_cb(void *data, Evas_Object *obj, void *event_info)
503 {
504     temperature_popup_fields *popup_fields = (temperature_popup_fields *)data;
505     Evas_Object *entry = popup_fields->entry;
506     const char *temperatureString = elm_entry_entry_get(entry);
507     // Remove white spaces(if any) at the beginning
508     int beginning = 0;
509     while (temperatureString[beginning] == ' ')
510     {
511         (beginning)++;
512     }
513
514     int len = strlen(temperatureString);
515     if (NULL == temperatureString || 1 > len)
516     {
517         dlog_print(DLOG_INFO, LOG_TAG, "#### Read NULL Temperature Value");
518         string logMessage = "Temperature Cannot be NULL<br>";
519         logMessage += "----------------------<br>";
520         dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
521         ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog, &logMessage);
522     }
523     else
524     {
525         int temperate = atoi(temperatureString);
526         string tempString(temperatureString);
527         setAttributeToRemoteServer(temperate);
528         dlog_print(DLOG_INFO, LOG_TAG, "#### Temperature to set : %d", temperate);
529
530         string logMessage = "Temperature to set : " + tempString + "<br>";
531         logMessage += "----------------------<br>";
532         dlog_print(DLOG_INFO, LOG_TAG, " %s", logMessage.c_str());
533         ecore_main_loop_thread_safe_call_sync((void * ( *)(void *))updateGroupLog,
534                                               &logMessage);
535     }
536     evas_object_del(popup_fields->popup);
537     free(popup_fields);
538 }
539
540 static void
541 list_scheduled_actionset_cb(void *data, Evas_Object *obj, void *event_info)
542 {
543     Evas_Object *popup, *btn;
544     Evas_Object *nf = naviframe;
545     Evas_Object *entry;
546     Evas_Object *layout;
547
548     /* popup */
549     popup = elm_popup_add(nf);
550     elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
551     eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, eext_popup_back_cb, NULL);
552     evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
553     elm_object_part_text_set(popup, "title,text", "Enter the temperature");
554
555     layout = elm_layout_add(popup);
556     elm_layout_file_set(layout, ELM_DEMO_EDJ, "popup_datetime_text");
557     evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
558     elm_object_content_set(popup, layout);
559
560     entry = elm_entry_add(layout);
561     elm_entry_single_line_set(entry, EINA_TRUE);
562     elm_entry_scrollable_set(entry, EINA_TRUE);
563     evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
564     evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
565     eext_entry_selection_back_event_allow_set(entry, EINA_TRUE);
566     elm_object_part_text_set(entry, "elm.guide", "in degree celsius");
567     elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NUMBER);
568     elm_object_part_content_set(layout, "elm.swallow.content", entry);
569
570     temperature_popup_fields *popup_fields;
571     popup_fields = (temperature_popup_fields *)malloc(sizeof(temperature_popup_fields));
572     if (NULL == popup_fields)
573     {
574         dlog_print(DLOG_INFO, LOG_TAG, "#### Memory allocation failed");
575     }
576     else
577     {
578         popup_fields->popup = popup;
579         popup_fields->entry = entry;
580     }
581
582     /* Cancel button */
583     btn = elm_button_add(popup);
584     elm_object_style_set(btn, "popup");
585     elm_object_text_set(btn, "Cancel");
586     elm_object_part_content_set(popup, "button1", btn);
587     evas_object_smart_callback_add(btn, "clicked", popup_cancel_clicked_cb, popup_fields);
588
589     /* Set button */
590     btn = elm_button_add(popup);
591     elm_object_style_set(btn, "popup");
592     elm_object_text_set(btn, "Set");
593     elm_object_part_content_set(popup, "button2", btn);
594     evas_object_smart_callback_add(btn, "clicked", popup_set_clicked_cb, popup_fields);
595
596     evas_object_show(popup);
597 }
598
599 // Method to be called when the Discover Resource UI Button is selected
600 static void
601 find_resource_cb(void *data, Evas_Object *obj, void *event_info)
602 {
603     if (NULL != list)
604     {
605         discoverResource();
606     }
607     else
608     {
609         dlog_print(DLOG_ERROR, "find_resource_cb", "list is NULL - So unable to add items!!!");
610     }
611 }
612
613 void *showClientAPIs(void *data)
614 {
615     // Add items to the list only if the list is empty
616     const Eina_List *eina_list = elm_list_items_get(list);
617     int count = eina_list_count(eina_list);
618     if (!count)
619     {
620         elm_list_item_append(list, "1. Start Monitoring", NULL, NULL,
621                              startMonitoring, NULL);
622
623         elm_list_item_append(list, "2. Stop Monitoring", NULL, NULL,
624                              stopMonitoring, NULL);
625
626         elm_list_item_append(list, "3. Get Attribute", NULL, NULL,
627                              getAttributeFromRemoteServer, NULL);
628
629         elm_list_item_append(list, "4. Set Attribute", NULL, NULL,
630                              list_scheduled_actionset_cb, NULL);
631
632         elm_list_item_append(list, "5. Start Caching - No update", NULL, NULL,
633                              startCachingWithoutCallback, NULL);
634
635         elm_list_item_append(list, "6. Start Caching - With update", NULL, NULL,
636                              startCachingWithCallback, NULL);
637
638         elm_list_item_append(list, "7. Get Cache State", NULL, NULL,
639                              getResourceCacheState, NULL);
640
641         elm_list_item_append(list, "8. Get cached attributes", NULL, NULL,
642                              getCachedAttributes, NULL);
643
644         elm_list_item_append(list, "9. Stop Caching", NULL, NULL,
645                              stopCaching, NULL);
646
647         elm_list_go(list);
648     }
649     return NULL;
650 }
651
652 static Eina_Bool
653 naviframe_pop_cb(void *data, Elm_Object_Item *it)
654 {
655     onDestroy();
656
657     if (NULL != log_entry)
658     {
659         evas_object_del(log_entry);
660         log_entry = NULL;
661     }
662     if (NULL != list)
663     {
664         evas_object_del(list);
665         list = NULL;
666     }
667     return EINA_TRUE;
668 }
669
670 // Method to be called when the Group APIs UI Button is selected
671 void group_cb(void *data, Evas_Object *obj, void *event_info)
672 {
673     Evas_Object *layout;
674     Evas_Object *scroller;
675     Evas_Object *nf = (Evas_Object *)data;
676     Evas_Object *find_button;
677     Elm_Object_Item *nf_it;
678
679     naviframe = nf;
680
681     // Scroller
682     scroller = elm_scroller_add(nf);
683     elm_scroller_bounce_set(scroller, EINA_FALSE, EINA_TRUE);
684     elm_scroller_policy_set(scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
685
686     // Layout
687     layout = elm_layout_add(nf);
688     elm_layout_file_set(layout, ELM_DEMO_EDJ, "group_layout");
689     evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
690
691     elm_object_content_set(scroller, layout);
692
693     // Button
694     find_button = elm_button_add(layout);
695     elm_object_part_content_set(layout, "find_button", find_button);
696     elm_object_text_set(find_button, "Discover Resource");
697     evas_object_smart_callback_add(find_button, "clicked", find_resource_cb, NULL);
698
699     // List
700     list = elm_list_add(layout);
701     elm_list_mode_set(list, ELM_LIST_COMPRESS);
702     evas_object_smart_callback_add(list, "selected", list_selected_cb, NULL);
703     elm_object_part_content_set(layout, "list", list);
704     elm_list_go(list);
705
706     // log_entry - textarea for log
707     log_entry = elm_entry_add(layout);
708     elm_entry_scrollable_set(log_entry, EINA_TRUE);
709     elm_entry_editable_set(log_entry, EINA_FALSE);
710     elm_object_part_text_set(log_entry, "elm.guide", "Logs will be updated here!!!");
711     evas_object_size_hint_weight_set(log_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
712     evas_object_size_hint_align_set(log_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
713     elm_object_part_content_set(layout, "log", log_entry);
714
715     nf_it = elm_naviframe_item_push(nf, "Resource Encapsulation", NULL, NULL, scroller, NULL);
716     elm_naviframe_item_pop_cb_set(nf_it, naviframe_pop_cb, NULL);
717 }