6368e93dc4e76ca75ed34390f47fe5609a7a76b7
[platform/upstream/iotivity.git] / resource / examples / lightserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 // Copyright 2014 Samsung Electronics All Rights Reserved.
5 //
6 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 //      http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 //
20 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21
22 ///
23 /// This sample provides steps to define an interface for a resource
24 /// (properties and methods) and host this resource on the server.
25 ///
26
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #include <functional>
31
32 #include <pthread.h>
33 #include <mutex>
34 #include <condition_variable>
35
36 #include "OCPlatform.h"
37 #include "OCApi.h"
38
39 using namespace OC;
40 using namespace std;
41 namespace PH = std::placeholders;
42
43 int gObservation = 0;
44 void * ChangeLightRepresentation (void *param);
45 void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
46
47 // Specifies secure or non-secure
48 // false: non-secure resource
49 // true: secure resource
50 bool isSecure = false;
51
52 /// Specifies whether Entity handler is going to do slow response or not
53 bool isSlowResponse = false;
54
55 // Forward declaring the entityHandler
56
57 /// This class represents a single resource named 'lightResource'. This resource has
58 /// one simple attribute, power
59
60 class LightResource
61 {
62
63 public:
64     /// Access this property from a TB client
65     std::string m_power;
66     std::string m_lightUri;
67     OCResourceHandle m_resourceHandle;
68     OCRepresentation m_lightRep;
69
70 public:
71     /// Constructor
72     LightResource()
73         :m_power(""), m_lightUri("/a/light") {
74         // Initialize representation
75         m_lightRep.setUri(m_lightUri);
76
77         m_lightRep.setValue("power", m_power);
78     }
79
80     /* Note that this does not need to be a member function: for classes you do not have
81     access to, you can accomplish this with a free function: */
82
83     /// This function internally calls registerResource API.
84     void createResource()
85     {
86         std::string resourceURI = m_lightUri; //URI of the resource
87         std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
88         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
89
90         EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
91
92         // This will internally create and register the resource.
93         OCStackResult result = OCPlatform::registerResource(
94                                     m_resourceHandle, resourceURI, resourceTypeName,
95                                     resourceInterface, cb, OC_DISCOVERABLE | OC_OBSERVABLE);
96
97         if (OC_STACK_OK != result)
98         {
99             cout << "Resource creation was unsuccessful\n";
100         }
101     }
102
103     OCResourceHandle getHandle()
104     {
105         return m_resourceHandle;
106     }
107
108     // Puts representation.
109     // Gets values from the representation and
110     // updates the internal state
111     void put(OCRepresentation& rep)
112     {
113         try {
114             if (rep.getValue("power", m_power))
115             {
116                 cout << "\t\t\t\t" << "power: " << m_power << endl;
117             }
118             else
119             {
120                 cout << "\t\t\t\t" << "power not found in the representation" << endl;
121             }
122         }
123         catch (exception& e)
124         {
125             cout << e.what() << endl;
126         }
127
128     }
129
130     // Post representation.
131     // Post can create new resource or simply act like put.
132     // Gets values from the representation and
133     // updates the internal state
134     OCRepresentation post(OCRepresentation& rep)
135     {
136         put(rep);
137         return get();
138     }
139
140
141     // gets the updated representation.
142     // Updates the representation with latest internal state before
143     // sending out.
144     OCRepresentation get()
145     {
146         m_lightRep.setValue("power", m_power);
147
148         return m_lightRep;
149     }
150
151     void addType(const std::string& type) const
152     {
153         OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
154         if (OC_STACK_OK != result)
155         {
156             cout << "Binding TypeName to Resource was unsuccessful\n";
157         }
158     }
159
160     void addInterface(const std::string& interface) const
161     {
162         OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
163         if (OC_STACK_OK != result)
164         {
165             cout << "Binding TypeName to Resource was unsuccessful\n";
166         }
167     }
168
169 private:
170 // This is just a sample implementation of entity handler.
171 // Entity handler can be implemented in several ways by the manufacturer
172 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
173 {
174     cout << "\tIn Server CPP entity handler:\n";
175     OCEntityHandlerResult ehResult = OC_EH_ERROR;
176     if(request)
177     {
178         // Get the request type and request flag
179         std::string requestType = request->getRequestType();
180         int requestFlag = request->getRequestHandlerFlag();
181
182         if(requestFlag & RequestHandlerFlag::RequestFlag)
183         {
184             cout << "\t\trequestFlag : Request\n";
185             auto pResponse = std::make_shared<OC::OCResourceResponse>();
186             pResponse->setRequestHandle(request->getRequestHandle());
187             pResponse->setResourceHandle(request->getResourceHandle());
188
189             // If the request type is GET
190             if(requestType == "GET")
191             {
192                 cout << "\t\t\trequestType : GET\n";
193                 if(isSlowResponse) // Slow response case
194                 {
195                     static int startedThread = 0;
196                     if(!startedThread)
197                     {
198                         std::thread t(handleSlowResponse, (void *)this, request);
199                         startedThread = 1;
200                         t.detach();
201                     }
202                     ehResult = OC_EH_SLOW;
203                 }
204                 else // normal response case.
205                 {
206                     pResponse->setErrorCode(200);
207                     pResponse->setResponseResult(OC_EH_OK);
208                     pResponse->setResourceRepresentation(get());
209                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
210                     {
211                         ehResult = OC_EH_OK;
212                     }
213                 }
214             }
215             else if(requestType == "PUT")
216             {
217                 cout << "\t\t\trequestType : PUT\n";
218                 OCRepresentation rep = request->getResourceRepresentation();
219
220                 // Do related operations related to PUT request
221                 // Update the lightResource
222                 put(rep);
223                 pResponse->setErrorCode(200);
224                 pResponse->setResponseResult(OC_EH_OK);
225                 pResponse->setResourceRepresentation(get());
226                 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
227                 {
228                     ehResult = OC_EH_OK;
229                 }
230             }
231             else if(requestType == "POST")
232             {
233                 cout << "\t\t\trequestType : POST\n";
234
235                 OCRepresentation rep = request->getResourceRepresentation();
236
237                 // Do related operations related to POST request
238                 OCRepresentation rep_post = post(rep);
239                 pResponse->setResourceRepresentation(rep_post);
240                 pResponse->setErrorCode(200);
241                 if(rep_post.hasAttribute("createduri"))
242                 {
243                     pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
244                     pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
245                 }
246
247                 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
248                 {
249                     ehResult = OC_EH_OK;
250                 }
251             }
252             else if(requestType == "DELETE")
253             {
254                 // DELETE request operations
255             }
256         }
257     }
258     else
259     {
260         std::cout << "Request invalid" << std::endl;
261     }
262
263     return ehResult;
264 }
265 };
266
267 void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
268 {
269     // This function handles slow response case
270     LightResource* lightPtr = (LightResource*) param;
271     // Induce a case for slow response by using sleep
272     std::cout << "SLOW response" << std::endl;
273     sleep (10);
274
275     auto pResponse = std::make_shared<OC::OCResourceResponse>();
276     pResponse->setRequestHandle(pRequest->getRequestHandle());
277     pResponse->setResourceHandle(pRequest->getResourceHandle());
278     pResponse->setResourceRepresentation(lightPtr->get());
279     pResponse->setErrorCode(200);
280     pResponse->setResponseResult(OC_EH_OK);
281
282     // Set the slow response flag back to false
283     isSlowResponse = false;
284     OCPlatform::sendResponse(pResponse);
285     return NULL;
286 }
287
288
289 int main(int /*argc*/, char** /*argv[]*/)
290 {
291     // Create PlatformConfig object
292     PlatformConfig cfg {
293         OC::ServiceType::InProc,
294         OC::ModeType::Server,
295         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
296         0,         // Uses randomly available port
297         OC::QualityOfService::LowQos
298     };
299
300     OCPlatform::Configure(cfg);
301     try
302     {
303         // Create the instance of the resource class
304         // (in this case instance of class 'LightResource').
305         LightResource myLight;
306
307         // Invoke createResource function of class light.
308         myLight.createResource();
309
310         myLight.addType(std::string("core.brightlight"));
311         myLight.addInterface(std::string(LINK_INTERFACE));
312
313         // A condition variable will free the mutex it is given, then do a non-
314         // intensive block until 'notify' is called on it.  In this case, since we
315         // don't ever call cv.notify, this should be a non-processor intensive version
316         // of while(true);
317         std::mutex blocker;
318         std::condition_variable cv;
319         std::unique_lock<std::mutex> lock(blocker);
320         cv.wait(lock);
321     }
322     catch(OCException& e)
323     {
324        oclog() << "Exception in main: "<< e.what();
325     }
326
327     // No explicit call to stop the platform.
328     // When OCPlatform::destructor is invoked, internally we do platform cleanup
329
330     return 0;
331 }
332