93bad63738a4b06e65f4f3c3561006b951b36213
[platform/upstream/iotivity.git] / service / protocol-plugin / plugins / mqtt-light / src / lightserver.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 /// This sample provides steps to define an interface for a resource
23 /// (properties and methods) and host this resource on the server.
24 ///
25
26 #include <functional>
27 #include <pthread.h>
28 #include <cpluff.h>
29
30 #include "OCPlatform.h"
31 #include "OCApi.h"
32 #include "../lib/mosquitto.h"
33 #include "lightserver.h"
34
35 #include <time.h>
36
37 using namespace OC;
38 using namespace std;
39 namespace PH = std::placeholders;
40
41 time_t timer;                // Define the timer
42 struct tm *tblock;           // Define a structure for time block
43
44 int gObservation = 0;
45 void *ChangeLightRepresentation (void *param);
46
47 // Specifies where to notify all observers or list of observers
48 // 0 - notifies all observers
49 // 1 - notifies list of observers
50 int isListOfObservers = 0;
51
52 // Forward declaring the entityHandler
53
54 /// This class represents a single resource named 'lightResource'. This resource has
55 /// two simple properties named 'state' and 'power'
56
57
58
59 // Forward declaring the entityHandler
60 // void entityHandler(std::shared_ptr<OCResourceRequest> request,
61 //                    std::shared_ptr<OCResourceResponse> response);
62
63 /// This class represents a single resource named 'lightResource'. This resource has
64 /// two simple properties named 'state' and 'power'
65 typedef struct plugin_data_t plugin_data_t;
66
67 struct plugin_data_t
68 {
69     cp_context_t *ctx;
70     pthread_t m_thread;                                 // 2
71     void *str;
72     bool flag;
73 };
74
75
76 class LightResource
77 {
78     public:
79         /// Access this property from a TB client
80         std::string m_name;
81         bool m_state;
82         int m_power;
83         int m_health;
84         std::string m_lightUri;
85         OCResourceHandle m_resourceHandle;
86         OCRepresentation m_lightRep;
87         ObservationIds m_interestedObservers;
88
89     public:
90         /// Constructor
91         LightResource(): m_name("John's light"), m_state(false), m_power(0), m_lightUri("/a/light")
92         {
93             // Initialize representation
94             m_lightRep.setUri(m_lightUri);
95
96             m_lightRep.setValue("state", m_state);
97             m_lightRep.setValue("power", m_power);
98             m_lightRep.setValue("name", m_name);
99         }
100
101
102         /* Note that this does not need to be a member function: for classes you do not have
103         access to, you can accomplish this with a free function: */
104
105         /// This function internally calls registerResource API.
106         void createResource()
107         {
108             std::string resourceURI = m_lightUri; // URI of the resource
109             std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
110             std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
111
112             // OCResourceProperty is defined ocstack.h
113             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
114
115             EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
116
117             // This will internally create and register the resource.
118             OCStackResult result = OCPlatform::registerResource(
119                                        m_resourceHandle, resourceURI, resourceTypeName,
120                                        resourceInterface, cb, resourceProperty);
121
122             if (OC_STACK_OK != result)
123             {
124                 cout << "Resource creation was unsuccessful\n";
125             }
126         }
127
128         OCStackResult createResource1()
129         {
130             std::string resourceURI = "/a/light1"; // URI of the resource
131             std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
132             std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
133
134             // OCResourceProperty is defined ocstack.h
135             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
136
137             EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
138
139             OCResourceHandle resHandle;
140
141             // This will internally create and register the resource.
142             OCStackResult result = OCPlatform::registerResource(
143                                        resHandle, resourceURI, resourceTypeName,
144                                        resourceInterface, cb, resourceProperty);
145
146             if (OC_STACK_OK != result)
147             {
148                 cout << "Resource creation was unsuccessful\n";
149             }
150
151             return result;
152         }
153
154         OCResourceHandle getHandle()
155         {
156             return m_resourceHandle;
157         }
158
159         // Puts representation.
160         // Gets values from the representation and
161         // updates the internal state
162         void put(OCRepresentation &rep)
163         {
164             try
165             {
166                 if (rep.getValue("state", m_state))
167                 {
168                     cout << "\t\t\t\t" << "state: " << m_state << endl;
169                 }
170                 else
171                 {
172                     cout << "\t\t\t\t" << "state not found in the representation" << endl;
173                 }
174
175                 if (rep.getValue("power", m_power))
176                 {
177                     cout << "\t\t\t\t" << "power: " << m_power << endl;
178                 }
179                 else
180                 {
181                     cout << "\t\t\t\t" << "power not found in the representation" << endl;
182                 }
183             }
184             catch (exception &e)
185             {
186                 cout << e.what() << endl;
187             }
188
189         }
190
191         // Post representation.
192         // Post can create new resource or simply act like put.
193         // Gets values from the representation and
194         // updates the internal state
195         OCRepresentation post(OCRepresentation &rep)
196         {
197             static int first = 1;
198
199             // for the first time it tries to create a resource
200             if (first)
201             {
202                 first = 0;
203
204                 if (OC_STACK_OK == createResource1())
205                 {
206                     OCRepresentation rep1;
207                     rep1.setValue("createduri", std::string("/a/light1"));
208
209                     return rep1;
210                 }
211             }
212
213             // from second time onwards it just puts
214             put(rep);
215             return get();
216         }
217
218
219         // gets the updated representation.
220         // Updates the representation with latest internal state before
221         // sending out.
222         OCRepresentation get()
223         {
224             m_lightRep.setValue("state", m_state);
225             m_lightRep.setValue("power", m_power);
226
227             return m_lightRep;
228         }
229
230
231         void addType(const std::string &type) const
232         {
233             OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
234             if (OC_STACK_OK != result)
235             {
236                 cout << "Binding TypeName to Resource was unsuccessful\n";
237             }
238         }
239
240         void addInterface(const std::string &interface) const
241         {
242             OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
243             if (OC_STACK_OK != result)
244             {
245                 cout << "Binding TypeName to Resource was unsuccessful\n";
246             }
247         }
248
249     private:
250         // This is just a sample implementation of entity handler.
251         // Entity handler can be implemented in several ways by the manufacturer
252         OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
253                                             std::shared_ptr<OCResourceResponse> response)
254         {
255             OCEntityHandlerResult result = OC_EH_OK;
256
257             cout << "\tIn Server CPP entity handler:\n";
258
259             if (request)
260             {
261                 // Get the request type and request flag
262                 std::string requestType = request->getRequestType();
263                 int requestFlag = request->getRequestHandlerFlag();
264
265                 if (requestFlag & RequestHandlerFlag::InitFlag)
266                 {
267                     cout << "\t\trequestFlag : Init\n";
268
269                     // entity handler to perform resource initialization operations
270                 }
271                 if (requestFlag & RequestHandlerFlag::RequestFlag)
272                 {
273                     cout << "\t\trequestFlag : Request ===  Handle by LightServer\n";
274
275                     // If the request type is GET
276                     if (requestType == "GET")
277                     {
278                         cout << "\t\t\trequestType : GET\n";
279
280                         if (response)
281                         {
282                             // TODO Error Code
283                             response->setErrorCode(200);
284
285                             response->setResourceRepresentation(get());
286                         }
287                     }
288                     else if (requestType == "PUT")
289                     {
290                         cout << "\t\t\trequestType : PUT\n";
291
292                         OCRepresentation rep = request->getResourceRepresentation();
293
294                         // Do related operations related to PUT request
295
296                         // Update the lightResource
297                         put(rep);
298
299                         if (response)
300                         {
301                             // TODO Error Code
302                             response->setErrorCode(200);
303
304                             response->setResourceRepresentation(get());
305                         }
306
307                     }
308                     else if (requestType == "POST")
309                     {
310                         cout << "\t\t\trequestType : POST\n";
311
312                         OCRepresentation rep = request->getResourceRepresentation();
313
314                         // Do related operations related to POST request
315
316                         OCRepresentation rep_post = post(rep);
317
318                         if (response)
319                         {
320                             // TODO Error Code
321                             response->setErrorCode(200);
322
323                             response->setResourceRepresentation(rep_post);
324
325                             if (rep_post.hasAttribute("createduri"))
326                             {
327                                 result = OC_EH_RESOURCE_CREATED;
328
329                                 response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
330                             }
331
332                         }
333
334                         // POST request operations
335                     }
336                     else if (requestType == "DELETE")
337                     {
338                         // DELETE request operations
339                     }
340                 }
341
342                 if (requestFlag & RequestHandlerFlag::ObserverFlag)
343                 {
344                     ObservationInfo observationInfo = request->getObservationInfo();
345                     if (ObserveAction::ObserveRegister == observationInfo.action)
346                     {
347                         m_interestedObservers.push_back(observationInfo.obsId);
348                     }
349                     else if (ObserveAction::ObserveUnregister == observationInfo.action)
350                     {
351                         m_interestedObservers.erase(std::remove(
352                                                         m_interestedObservers.begin(),
353                                                         m_interestedObservers.end(),
354                                                         observationInfo.obsId),
355                                                     m_interestedObservers.end());
356                     }
357
358                     pthread_t threadId;
359
360                     cout << "\t\trequestFlag : Observer\n";
361                     gObservation = 1;
362                     static int startedThread = 0;
363
364                     // Observation happens on a different thread in ChangeLightRepresentation function.
365                     // If we have not created the thread already, we will create one here.
366                     if (!startedThread)
367                     {
368                         pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
369                         startedThread = 1;
370                     }
371                 }
372             }
373             else
374             {
375                 std::cout << "Request invalid" << std::endl;
376             }
377
378             return result;
379         }
380 };
381
382 // Create the instance of the resource class (in this case instance of class 'LightResource').
383 struct mosquitto *myMosquitto;
384
385 // ChangeLightRepresentaion is an observation function,
386 // which notifies any changes to the resource to stack
387 // via notifyObservers
388 void *ChangeLightRepresentation (void *param)
389 {
390     LightResource *lightPtr = (LightResource *) param;
391
392     // This function continuously monitors for the changes
393     while (1)
394     {
395         sleep (5);
396
397         if (gObservation)
398         {
399             // If under observation if there are any changes to the light resource
400             // we call notifyObservors
401             //
402             // For demostration we are changing the power value and notifying.
403             lightPtr->m_power += 10;
404
405             cout << "\nPower updated to : " << lightPtr->m_power << endl;
406             cout << "Notifying observers with resource handle: " << lightPtr->getHandle() << endl;
407
408             OCStackResult result = OC_STACK_OK;
409
410             if (isListOfObservers)
411             {
412                 std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
413
414                 resourceResponse->setErrorCode(200);
415                 resourceResponse->setResourceRepresentation(lightPtr->get(), DEFAULT_INTERFACE);
416
417                 result = OCPlatform::notifyListOfObservers(  lightPtr->getHandle(),
418                          lightPtr->m_interestedObservers,
419                          resourceResponse);
420             }
421             else
422             {
423                 result = OCPlatform::notifyAllObservers(lightPtr->getHandle());
424             }
425
426             if (OC_STACK_NO_OBSERVERS == result)
427             {
428                 cout << "No More observers, stopping notifications" << endl;
429                 gObservation = 0;
430             }
431         }
432     }
433
434     return NULL;
435 }
436
437
438
439
440 //int start_lightserver(void*)                // 1
441 void *start_lightserver(void *d)      // 2
442 {
443     /*PlatformConfig cfg;
444     cfg.ipAddress = "192.168.2.5";
445     cfg.port = 56832;
446     cfg.mode = ModeType::Server;
447     cfg.serviceType = ServiceType::InProc;*/
448     // PlatformConfig cfg
449     // {
450     //     OC::ServiceType::InProc,
451     //     OC::ModeType::Server,
452     //     "192.168.2.5",
453     //     56832,
454     //     OC::QualityOfService::NonConfirmable
455     // };
456
457     // Create PlatformConfig object
458
459     // Create a OCPlatform instance.
460     // Note: Platform creation is synchronous call.
461
462     // Create PlatformConfig object
463     PlatformConfig cfg
464     {
465         OC::ServiceType::InProc,
466         OC::ModeType::Server,
467         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
468         0,         // Uses randomly available port
469         OC::QualityOfService::LowQos
470     };
471
472     OCPlatform::Configure(cfg);
473
474     printf("start_fanserver [mosquitto] Null\n");
475     try
476     {
477         LightResource myLightResource;
478         mosquitto_lib_init();
479         myMosquitto = mosquitto_new("MQTT plug-in", true, NULL);
480         if (!myMosquitto)
481         {
482             printf("[mosquitto] Null\n");
483             printf("You need to install mqtt broker\n");
484         }
485         else
486         {
487             printf("Mosquitto is working\n");
488         }
489
490         //plugin_data_t *data = (plugin_data_t *)d;
491         //OCPlatform *platform = (OCPlatform*)data->str;
492         //myLightResource.m_platform = (OCPlatform*)data->str;
493         //OCPlatform platform(cfg);
494         // Invoke createResource function of class light.
495
496         //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
497         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
498         printf("Mosquitto Connection is done\n");
499         myLightResource.createResource();
500         //myLightResource.addType(std::string("core.light"));
501         //myLightResource.addInterface(std::string("oc.mi.ll"));
502         // Get time of day
503         timer = time(NULL);
504         // Converts date/time to a structure
505         tblock = localtime(&timer);
506         // Output ASCII data/time
507         printf("LightReousrce reigishter time is: %s", asctime(tblock));
508         // Perform app tasks
509         while (true)
510         {
511             // some tasks
512         }
513     }
514     catch (OCException e)
515     {
516         //log(e.what());
517     }
518     // No explicit call to stop the platform.
519     // When OCPlatform destructor is invoked, internally we do platform cleanup
520     mosquitto_destroy(myMosquitto);
521
522     mosquitto_lib_cleanup();
523     printf("start_lightserver finish\n");
524     pthread_exit((void *)0);
525 }