Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / resource / 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 refrigerator 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)=0;
54 };
55
56 class DeviceResource : public Resource
57 {
58     public:
59
60     DeviceResource():m_modelName{}
61     {
62         std::string resourceURI = "/device";
63         std::string resourceTypeName = "intel.fridge";
64         std::string resourceInterface = DEFAULT_INTERFACE;
65         EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1);
66
67         EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
68                                             ,this, PH::_1);
69
70         std::cout << "Setting device default entity handler\n";
71         OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
72
73         uint8_t resourceProperty = OC_DISCOVERABLE;
74         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
75             resourceURI,
76             resourceTypeName,
77             resourceInterface,
78             cb,
79             resourceProperty);
80
81         if(OC_STACK_OK != result)
82         {
83             throw std::runtime_error(
84                 std::string("Device Resource failed to start")+std::to_string(result));
85         }
86     }
87     private:
88     OCRepresentation get()
89     {
90         m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
91         return m_rep;
92     }
93
94     OCStackResult deleteDeviceResource()
95     {
96         OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
97         if(OC_STACK_OK != result)
98         {
99             throw std::runtime_error(
100                std::string("Device Resource failed to unregister/delete") + std::to_string(result));
101         }
102         return result;
103     }
104
105     std::string m_modelName;
106     protected:
107     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
108     {
109         OCEntityHandlerResult ehResult = OC_EH_ERROR;
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                     auto pResponse = std::make_shared<OC::OCResourceResponse>();
156                     pResponse->setRequestHandle(request->getRequestHandle());
157                     pResponse->setResourceHandle(request->getResourceHandle());
158                     pResponse->setHeaderOptions(serverHeaderOptions);
159
160                     if(request->getRequestType() == "GET")
161                     {
162                         std::cout<<"DeviceResource Get Request"<<std::endl;
163                         pResponse->setErrorCode(200);
164                         pResponse->setResponseResult(OC_EH_OK);
165                         pResponse->setResourceRepresentation(get(), "");
166                         if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
167                         {
168                             ehResult = OC_EH_OK;
169                         }
170                     }
171                     else if(request->getRequestType() == "DELETE")
172                     {
173                         std::cout<<"DeviceResource Delete Request"<<std::endl;
174                         if(deleteDeviceResource() == OC_STACK_OK)
175                         {
176                             pResponse->setErrorCode(200);
177                             pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
178                             ehResult = OC_EH_OK;
179                         }
180                         else
181                         {
182                             pResponse->setResponseResult(OC_EH_ERROR);
183                             ehResult = OC_EH_ERROR;
184                         }
185                         OCPlatform::sendResponse(pResponse);
186                     }
187                     else
188                     {
189                         std::cout <<"DeviceResource unsupported request type "
190                         << request->getRequestType() << std::endl;
191                         pResponse->setResponseResult(OC_EH_ERROR);
192                         OCPlatform::sendResponse(pResponse);
193                         ehResult = OC_EH_ERROR;
194                     }
195                 }
196                 else
197                 {
198                     std::cout << "DeviceResource unsupported request flag" <<std::endl;
199                 }
200             }
201             else
202             {
203                 std::cout << "Unsupported/invalid header options/values" << std::endl;
204             }
205         }
206
207         return ehResult;
208     }
209
210     virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
211     {
212         OCEntityHandlerResult ehResult = OC_EH_ERROR;
213         if(request)
214         {
215             std::cout << "In Default Entity Handler, uri received: "
216                         << request->getResourceUri() << std::endl;
217
218             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
219             {
220                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
221                 pResponse->setRequestHandle(request->getRequestHandle());
222                 pResponse->setResourceHandle(request->getResourceHandle());
223
224                 if(request->getRequestType() == "GET")
225                 {
226                     std::cout<<"Default Entity Handler: Get Request"<<std::endl;
227                     pResponse->setErrorCode(200);
228                     pResponse->setResourceRepresentation(get(), "");
229                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
230                     {
231                         ehResult = OC_EH_OK;
232                     }
233                 }
234                 else
235                 {
236                     std::cout <<"Default Entity Handler: unsupported request type "
237                     << request->getRequestType() << std::endl;
238                     pResponse->setResponseResult(OC_EH_ERROR);
239                     OCPlatform::sendResponse(pResponse);
240                     ehResult = OC_EH_ERROR;
241                 }
242             }
243             else
244             {
245                 std::cout << "Default Entity Handler: unsupported request flag" <<std::endl;
246             }
247         }
248
249         return ehResult;
250    }
251
252 };
253
254 class LightResource : public Resource
255 {
256     public:
257     LightResource() : m_isOn(false)
258     {
259         std::string resourceURI = "/light";
260         std::string resourceTypeName = "intel.fridge.light";
261         std::string resourceInterface = DEFAULT_INTERFACE;
262         EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
263         uint8_t resourceProperty = 0;
264         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
265             resourceURI,
266             resourceTypeName,
267             resourceInterface,
268             cb,
269             resourceProperty);
270
271         if(OC_STACK_OK != result)
272         {
273             throw std::runtime_error(
274                 std::string("Light Resource failed to start")+std::to_string(result));
275         }
276     }
277     private:
278     OCRepresentation get()
279     {
280         m_rep.setValue("on", m_isOn);
281         return m_rep;
282     }
283
284     void put(const OCRepresentation& rep)
285     {
286         rep.getValue("on", m_isOn);
287     }
288
289     bool m_isOn;
290     protected:
291     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
292     {
293         OCEntityHandlerResult ehResult = OC_EH_ERROR;
294         if(request)
295         {
296             std::cout << "In entity handler for Light, URI is : "
297                       << request->getResourceUri() << std::endl;
298
299             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
300             {
301                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
302                 pResponse->setRequestHandle(request->getRequestHandle());
303                 pResponse->setResourceHandle(request->getResourceHandle());
304
305                 if(request->getRequestType() == "GET")
306                 {
307                     std::cout<<"Light Get Request"<<std::endl;
308                     pResponse->setErrorCode(200);
309                     pResponse->setResourceRepresentation(get(), "");
310                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
311                     {
312                         ehResult = OC_EH_OK;
313                     }
314                 }
315                 else if(request->getRequestType() == "PUT")
316                 {
317                     std::cout <<"Light Put Request"<<std::endl;
318                     put(request->getResourceRepresentation());
319                     pResponse->setErrorCode(200);
320                     pResponse->setResourceRepresentation(get(), "");
321                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
322                     {
323                         ehResult = OC_EH_OK;
324                     }
325                 }
326                 else
327                 {
328                     std::cout << "Light unsupported request type"
329                     << request->getRequestType() << std::endl;
330                     pResponse->setResponseResult(OC_EH_ERROR);
331                     OCPlatform::sendResponse(pResponse);
332                     ehResult = OC_EH_ERROR;
333                 }
334             }
335             else
336             {
337                 std::cout << "Light unsupported request flag" <<std::endl;
338             }
339         }
340
341         return ehResult;
342     }
343 };
344
345 class DoorResource : public Resource
346 {
347     public:
348     DoorResource(const std::string& side):m_isOpen{false}, m_side(side)
349     {
350
351         std::string resourceURI = "/door/"+ side;
352         std::string resourceTypeName = "intel.fridge.door";
353         std::string resourceInterface = DEFAULT_INTERFACE;
354         EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
355
356         uint8_t resourceProperty = 0;
357         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
358             resourceURI,
359             resourceTypeName,
360             resourceInterface,
361             cb,
362             resourceProperty);
363
364         if(OC_STACK_OK != result)
365         {
366             throw std::runtime_error(
367                 std::string("Door Resource failed to start")+std::to_string(result));
368         }
369     }
370
371     private:
372     OCRepresentation get()
373     {
374         m_rep.setValue("open", m_isOpen);
375         m_rep.setValue("side", m_side);
376         return m_rep;
377     }
378
379     void put(const OCRepresentation& rep)
380     {
381         rep.getValue("open", m_isOpen);
382         // Note, we won't let the user change the door side!
383     }
384     bool m_isOpen;
385     std::string m_side;
386     protected:
387     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
388     {
389         std::cout << "EH of door invoked " << std::endl;
390         OCEntityHandlerResult ehResult = OC_EH_ERROR;
391
392         if(request)
393         {
394             std::cout << "In entity handler for Door, URI is : "
395                       << request->getResourceUri() << std::endl;
396
397             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
398             {
399                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
400                 pResponse->setRequestHandle(request->getRequestHandle());
401                 pResponse->setResourceHandle(request->getResourceHandle());
402
403                 if(request->getRequestType() == "GET")
404                 {
405                     // note that we know the side because std::bind gives us the
406                     // appropriate object
407                     std::cout<< m_side << " Door Get Request"<<std::endl;
408                     pResponse->setErrorCode(200);
409                     pResponse->setResourceRepresentation(get(), "");
410                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
411                     {
412                         ehResult = OC_EH_OK;
413                     }
414                 }
415                 else if(request->getRequestType() == "PUT")
416                 {
417                     std::cout << m_side <<" Door Put Request"<<std::endl;
418                     put(request->getResourceRepresentation());
419                     pResponse->setErrorCode(200);
420                     pResponse->setResourceRepresentation(get(),"");
421                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
422                     {
423                         ehResult = OC_EH_OK;
424                     }
425                 }
426                 else
427                 {
428                     std::cout <<m_side<<" Door unsupported request type "
429                     << request->getRequestType() << std::endl;
430                     pResponse->setResponseResult(OC_EH_ERROR);
431                     OCPlatform::sendResponse(pResponse);
432                     ehResult = OC_EH_ERROR;
433                 }
434             }
435             else
436             {
437                 std::cout << "Door unsupported request flag" <<std::endl;
438             }
439         }
440
441         return ehResult;
442     }
443
444 };
445
446 class Refrigerator
447 {
448     public:
449     Refrigerator()
450         :
451         m_light(),
452         m_device(),
453         m_leftdoor("left"),
454         m_rightdoor("right")
455     {
456     }
457     private:
458     LightResource m_light;
459     DeviceResource m_device;
460     DoorResource m_leftdoor;
461     DoorResource m_rightdoor;
462 };
463
464 int main ()
465 {
466     PlatformConfig cfg
467     {
468         ServiceType::InProc,
469         ModeType::Server,
470         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
471         0,         // Uses randomly available port
472         QualityOfService::LowQos
473     };
474
475     OCPlatform::Configure(cfg);
476     Refrigerator rf;
477
478     // we will keep the server alive for at most 30 minutes
479     std::this_thread::sleep_for(std::chrono::minutes(30));
480     return 0;
481 }
482