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