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