iotivity 0.9.0
[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 /// two simple properties named 'state' and '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::InitFlag)
180         {
181             cout << "\t\trequestFlag : Init\n";
182
183             // entity handler to perform resource initialization operations
184         }
185         if(requestFlag & RequestHandlerFlag::RequestFlag)
186         {
187             cout << "\t\trequestFlag : Request\n";
188             auto pResponse = std::make_shared<OC::OCResourceResponse>();
189             pResponse->setRequestHandle(request->getRequestHandle());
190             pResponse->setResourceHandle(request->getResourceHandle());
191
192             // If the request type is GET
193             if(requestType == "GET")
194             {
195                 cout << "\t\t\trequestType : GET\n";
196                 if(isSlowResponse) // Slow response case
197                 {
198                     static int startedThread = 0;
199                     if(!startedThread)
200                     {
201                         std::thread t(handleSlowResponse, (void *)this, request);
202                         startedThread = 1;
203                         t.detach();
204                     }
205                     ehResult = OC_EH_SLOW;
206                 }
207                 else // normal response case.
208                 {
209                     pResponse->setErrorCode(200);
210                     pResponse->setResponseResult(OC_EH_OK);
211                     pResponse->setResourceRepresentation(get());
212                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
213                     {
214                         ehResult = OC_EH_OK;
215                     }
216                 }
217             }
218             else if(requestType == "PUT")
219             {
220                 cout << "\t\t\trequestType : PUT\n";
221                 OCRepresentation rep = request->getResourceRepresentation();
222
223                 // Do related operations related to PUT request
224                 // Update the lightResource
225                 put(rep);
226                 pResponse->setErrorCode(200);
227                 pResponse->setResponseResult(OC_EH_OK);
228                 pResponse->setResourceRepresentation(get());
229                 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
230                 {
231                     ehResult = OC_EH_OK;
232                 }
233             }
234             else if(requestType == "POST")
235             {
236                 cout << "\t\t\trequestType : POST\n";
237
238                 OCRepresentation rep = request->getResourceRepresentation();
239
240                 // Do related operations related to POST request
241                 OCRepresentation rep_post = post(rep);
242                 pResponse->setResourceRepresentation(rep_post);
243                 pResponse->setErrorCode(200);
244                 if(rep_post.hasAttribute("createduri"))
245                 {
246                     pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
247                     pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
248                 }
249
250                 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
251                 {
252                     ehResult = OC_EH_OK;
253                 }
254             }
255             else if(requestType == "DELETE")
256             {
257                 // DELETE request operations
258             }
259         }
260     }
261     else
262     {
263         std::cout << "Request invalid" << std::endl;
264     }
265
266     return ehResult;
267 }
268 };
269
270 void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
271 {
272     // This function handles slow response case
273     LightResource* lightPtr = (LightResource*) param;
274     // Induce a case for slow response by using sleep
275     std::cout << "SLOW response" << std::endl;
276     sleep (10);
277
278     auto pResponse = std::make_shared<OC::OCResourceResponse>();
279     pResponse->setRequestHandle(pRequest->getRequestHandle());
280     pResponse->setResourceHandle(pRequest->getResourceHandle());
281     pResponse->setResourceRepresentation(lightPtr->get());
282     pResponse->setErrorCode(200);
283     pResponse->setResponseResult(OC_EH_OK);
284
285     // Set the slow response flag back to false
286     isSlowResponse = false;
287     OCPlatform::sendResponse(pResponse);
288     return NULL;
289 }
290
291
292 int main(int argc, char* argv[])
293 {
294     // Create PlatformConfig object
295     PlatformConfig cfg {
296         OC::ServiceType::InProc,
297         OC::ModeType::Server,
298         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
299         0,         // Uses randomly available port
300         OC::QualityOfService::LowQos
301     };
302
303     OCPlatform::Configure(cfg);
304     try
305     {
306         // Create the instance of the resource class
307         // (in this case instance of class 'LightResource').
308         LightResource myLight;
309
310         // Invoke createResource function of class light.
311         myLight.createResource();
312
313         myLight.addType(std::string("core.brightlight"));
314         myLight.addInterface(std::string("oc.mi.ll"));
315
316         // A condition variable will free the mutex it is given, then do a non-
317         // intensive block until 'notify' is called on it.  In this case, since we
318         // don't ever call cv.notify, this should be a non-processor intensive version
319         // of while(true);
320         std::mutex blocker;
321         std::condition_variable cv;
322         std::unique_lock<std::mutex> lock(blocker);
323         cv.wait(lock);
324     }
325     catch(OCException e)
326     {
327         //log(e.what());
328     }
329
330     // No explicit call to stop the platform.
331     // When OCPlatform::destructor is invoked, internally we do platform cleanup
332
333     return 0;
334 }