3700e3099d0a3d6a33753bdac863c169e1ff4488
[platform/upstream/iotivity.git] / examples / fridgeserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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 /// The purpose of this server is to simulate a refridgerator that contains a device resource for
22 /// its description, a light resource for the internal light, and 2 door resources for the purpose
23 /// of representing the doors attached to this fridge.  This is used by the fridgeclient to
24 /// demonstrate using std::bind to attach to instances of a class as well as using
25 /// constructResourceObject
26
27 #include <chrono>
28 #include <iostream>
29 #include <thread>
30 #include <stdexcept>
31
32 #include "OCPlatform.h"
33 #include "OCApi.h"
34
35 using namespace OC;
36 namespace PH = std::placeholders;
37
38 // Option ID for API version and client token
39 const uint16_t API_VERSION = 2048;
40 const uint16_t TOKEN = 3000;
41
42 // Setting API version and token (shared out of band with client)
43 // This assumes the fact that this server responds
44 // only with a server with below version and token
45 const std::string FRIDGE_CLIENT_API_VERSION = "v.1.0";
46 const std::string FRIDGE_CLIENT_TOKEN = "21ae43gf";
47
48 class Resource
49 {
50     protected:
51     OCResourceHandle m_resourceHandle;
52     OCRepresentation m_rep;
53     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
54             std::shared_ptr<OCResourceResponse> response)=0;
55 };
56
57 class DeviceResource : public Resource
58 {
59     public:
60
61     DeviceResource()
62     {
63         std::string resourceURI = "/device";
64         std::string resourceTypeName = "intel.fridge";
65         std::string resourceInterface = DEFAULT_INTERFACE;
66         EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1, PH::_2);
67
68         EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler, this,
69                                                                          PH::_1, PH::_2);
70
71         std::cout << "Setting device default entity handler\n";
72         OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
73
74         uint8_t resourceProperty = OC_DISCOVERABLE;
75         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
76             resourceURI,
77             resourceTypeName,
78             resourceInterface,
79             cb,
80             resourceProperty);
81
82         if(OC_STACK_OK != result)
83         {
84             throw std::runtime_error(
85                 std::string("Device Resource failed to start")+std::to_string(result));
86         }
87     }
88     private:
89     OCRepresentation get()
90     {
91         m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refridgerator"));
92         return m_rep;
93     }
94
95     void deleteDeviceResource()
96     {
97         OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
98         if(OC_STACK_OK != result)
99         {
100             throw std::runtime_error(
101                std::string("Device Resource failed to unregister/delete") + std::to_string(result));
102         }
103     }
104
105     std::string m_modelName;
106     protected:
107     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
108             std::shared_ptr<OCResourceResponse> response)
109     {
110         if(request)
111         {
112             // Get the header options from the request
113             HeaderOptions headerOptions = request->getHeaderOptions();
114             std::string clientAPIVersion;
115             std::string clientToken;
116
117             // Search the header options map and look for API version and Client token
118             for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
119             {
120                 uint16_t optionID = it->getOptionID();
121                 if(optionID == API_VERSION)
122                 {
123                     clientAPIVersion = it->getOptionData();
124                     std::cout << " Client API version: " << clientAPIVersion << std::endl;
125                 }
126                 else if(optionID == TOKEN)
127                 {
128                     clientToken = it->getOptionData();
129                     std::cout << " Client token: " << clientToken << std::endl;
130                 }
131                 else
132                 {
133                     std::cout << " Invalid header option " << std::endl;
134                 }
135             }
136
137             // In this case Server entity handler verifies API version
138             // and client token. If they are valid, client requests are handled.
139             if(clientAPIVersion == FRIDGE_CLIENT_API_VERSION && clientToken == FRIDGE_CLIENT_TOKEN)
140             {
141                 HeaderOptions serverHeaderOptions;
142                 try
143                 {
144                     // Set API version from server side
145                     HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION);
146                     serverHeaderOptions.push_back(apiVersion);
147                 }
148                 catch(OCException& e)
149                 {
150                     std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl;
151                 }
152
153                 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
154                 {
155                     if(request->getRequestType() == "GET")
156                     {
157                         if(response)
158                         {
159                             std::cout<<"DeviceResource Get Request"<<std::endl;
160                             response->setErrorCode(200);
161                             response->setHeaderOptions(serverHeaderOptions);
162                             response->setResourceRepresentation(get(), "");
163                         }
164                     }
165                     if(request->getRequestType() == "DELETE")
166                     {
167                         if(response)
168                         {
169                             std::cout<<"DeviceResource Delete Request"<<std::endl;
170                             deleteDeviceResource();
171                             response->setErrorCode(200);
172                             response->setHeaderOptions(serverHeaderOptions);
173                         }
174                     }
175                     else
176                     {
177                         std::cout <<"DeviceResource unsupported request type "
178                         << request->getRequestType() << std::endl;
179                     }
180                 }
181                 else
182                 {
183                     std::cout << "DeviceResource unsupported request flag" <<std::endl;
184                 }
185             }
186             else
187             {
188                 std::cout << "Unsupported/invalid header options/values" << std::endl;
189             }
190         }
191
192         return OC_EH_OK;
193     }
194
195     virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request,
196             std::shared_ptr<OCResourceResponse> response)
197     {
198         if(request)
199         {
200             std::cout << "In Default Entity Handler, uri received: "
201                         << request->getResourceUri() << std::endl;
202
203             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
204             {
205                 if(request->getRequestType() == "GET")
206                 {
207                     if(response)
208                     {
209                         std::cout<<"Default Entity Handler: Get Request"<<std::endl;
210                         response->setErrorCode(200);
211                         response->setResourceRepresentation(get(), "");
212                     }
213                 }
214                 else
215                 {
216                     std::cout <<"Default Entity Handler: unsupported request type "
217                     << request->getRequestType() << std::endl;
218                 }
219             }
220             else
221             {
222                 std::cout << "Default Entity Handler: unsupported request flag" <<std::endl;
223             }
224         }
225
226         return OC_EH_OK;
227    }
228
229 };
230
231 class LightResource : public Resource
232 {
233     public:
234     LightResource()
235     {
236         std::string resourceURI = "/light";
237         std::string resourceTypeName = "intel.fridge.light";
238         std::string resourceInterface = DEFAULT_INTERFACE;
239         EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
240         uint8_t resourceProperty = 0;
241         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
242             resourceURI,
243             resourceTypeName,
244             resourceInterface,
245             cb,
246             resourceProperty);
247
248         if(OC_STACK_OK != result)
249         {
250             throw std::runtime_error(
251                 std::string("Light Resource failed to start")+std::to_string(result));
252         }
253     }
254     private:
255     OCRepresentation get()
256     {
257         m_rep.setValue("on", m_isOn);
258         return m_rep;
259     }
260
261     void put(OCRepresentation rep)
262     {
263         rep.getValue("on", m_isOn);
264     }
265
266     bool m_isOn;
267     protected:
268     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
269             std::shared_ptr<OCResourceResponse> response)
270     {
271         if(request)
272         {
273             std::cout << "In entity handler for Light, URI is : "
274                       << request->getResourceUri() << std::endl;
275
276             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
277             {
278                 if(request->getRequestType() == "GET")
279                 {
280                     if(response)
281                     {
282                         std::cout<<"Light Get Request"<<std::endl;
283                         response->setErrorCode(200);
284                         response->setResourceRepresentation(get(), "");
285                     }
286                 }
287                 else if(request->getRequestType() == "PUT")
288                 {
289                     if(response)
290                     {
291                         std::cout <<"Light Put Request"<<std::endl;
292                         put(request->getResourceRepresentation());
293
294                         response->setErrorCode(200);
295                         response->setResourceRepresentation(get(),"");
296                     }
297                 }
298                 else
299                 {
300                     std::cout << "Light unsupported request type"
301                     << request->getRequestType() << std::endl;
302                 }
303             }
304             else
305             {
306                 std::cout << "Light unsupported request flag" <<std::endl;
307             }
308         }
309
310         return OC_EH_OK;
311     }
312 };
313
314 class DoorResource : public Resource
315 {
316     public:
317     DoorResource(const std::string& side):m_side(side)
318     {
319
320         std::string resourceURI = "/door/"+ side;
321         std::string resourceTypeName = "intel.fridge.door";
322         std::string resourceInterface = DEFAULT_INTERFACE;
323         EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1, PH::_2);
324
325         uint8_t resourceProperty = 0;
326         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
327             resourceURI,
328             resourceTypeName,
329             resourceInterface,
330             cb,
331             resourceProperty);
332
333         if(OC_STACK_OK != result)
334         {
335             throw std::runtime_error(
336                 std::string("Door Resource failed to start")+std::to_string(result));
337         }
338     }
339
340     private:
341     OCRepresentation get()
342     {
343         m_rep.setValue("open", m_isOpen);
344         m_rep.setValue("side", m_side);
345         return m_rep;
346     }
347
348     void put(OCRepresentation rep)
349     {
350         rep.getValue("open", m_isOpen);
351         // Note, we won't let the user change the door side!
352     }
353     bool m_isOpen;
354     std::string m_side;
355     protected:
356     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
357             std::shared_ptr<OCResourceResponse> response)
358     {
359         std::cout << "EH of door invoked " << std::endl;
360         if(request)
361         {
362             std::cout << "In entity handler for Door, URI is : "
363                       << request->getResourceUri() << std::endl;
364
365             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
366             {
367                 if(request->getRequestType() == "GET")
368                 {
369                     if(response)
370                     {
371                         // note that we know the side because std::bind gives us the
372                         // appropriate object
373                         std::cout<<m_side << " Door Get Request"<<std::endl;
374                         response->setErrorCode(200);
375                         response->setResourceRepresentation(get(), "");
376                     }
377                 }
378                 else if(request->getRequestType() == "PUT")
379                 {
380                     if(response)
381                     {
382                         std::cout <<m_side <<" Door Put Request"<<std::endl;
383                         put(request->getResourceRepresentation());
384                         response->setErrorCode(200);
385                         response->setResourceRepresentation(get(),"");
386                     }
387                 }
388                 else
389                 {
390                     std::cout <<m_side<<" Door unsupported request type "
391                     << request->getRequestType() << std::endl;
392                 }
393             }
394             else
395             {
396                 std::cout << "Door unsupported request flag" <<std::endl;
397             }
398         }
399
400         return OC_EH_OK;
401     }
402
403 };
404
405 class Refrigerator
406 {
407     public:
408     Refrigerator()
409         :
410         m_light(),
411         m_device(),
412         m_leftdoor("left"),
413         m_rightdoor("right")
414     {
415     }
416     private:
417     LightResource m_light;
418     DeviceResource m_device;
419     DoorResource m_leftdoor;
420     DoorResource m_rightdoor;
421 };
422
423 int main ()
424 {
425     PlatformConfig cfg
426     {
427         ServiceType::InProc,
428         ModeType::Server,
429         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
430         0,         // Uses randomly available port
431         QualityOfService::LowQos
432     };
433
434     OCPlatform::Configure(cfg);
435     Refrigerator rf;
436
437     // we will keep the server alive for at most 30 minutes
438     std::this_thread::sleep_for(std::chrono::minutes(30));
439     return 0;
440 }