556b34c722cb1003af35ecb298aefbbe1b137def
[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             // Get the message ID from the request
118             std::cout << " MessageID: " << request->getMessageID() << std::endl;
119
120             // Search the header options map and look for API version and Client token
121             for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
122             {
123                 uint16_t optionID = it->getOptionID();
124                 if(optionID == API_VERSION)
125                 {
126                     clientAPIVersion = it->getOptionData();
127                     std::cout << " Client API version: " << clientAPIVersion << std::endl;
128                 }
129                 else if(optionID == TOKEN)
130                 {
131                     clientToken = it->getOptionData();
132                     std::cout << " Client token: " << clientToken << std::endl;
133                 }
134                 else
135                 {
136                     std::cout << " Invalid header option " << std::endl;
137                 }
138             }
139
140             // In this case Server entity handler verifies API version
141             // and client token. If they are valid, client requests are handled.
142             if(clientAPIVersion == FRIDGE_CLIENT_API_VERSION && clientToken == FRIDGE_CLIENT_TOKEN)
143             {
144                 HeaderOptions serverHeaderOptions;
145                 try
146                 {
147                     // Set API version from server side
148                     HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION);
149                     serverHeaderOptions.push_back(apiVersion);
150                 }
151                 catch(OCException& e)
152                 {
153                     std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl;
154                 }
155
156                 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
157                 {
158                     auto pResponse = std::make_shared<OC::OCResourceResponse>();
159                     pResponse->setRequestHandle(request->getRequestHandle());
160                     pResponse->setResourceHandle(request->getResourceHandle());
161                     pResponse->setHeaderOptions(serverHeaderOptions);
162
163                     if(request->getRequestType() == "GET")
164                     {
165                         std::cout<<"DeviceResource Get Request"<<std::endl;
166                         pResponse->setErrorCode(200);
167                         pResponse->setResponseResult(OC_EH_OK);
168                         pResponse->setResourceRepresentation(get(), "");
169                         if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
170                         {
171                             ehResult = OC_EH_OK;
172                         }
173                     }
174                     else if(request->getRequestType() == "DELETE")
175                     {
176                         std::cout<<"DeviceResource Delete Request"<<std::endl;
177                         if(deleteDeviceResource() == OC_STACK_OK)
178                         {
179                             pResponse->setErrorCode(200);
180                             pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
181                             ehResult = OC_EH_OK;
182                         }
183                         else
184                         {
185                             pResponse->setResponseResult(OC_EH_ERROR);
186                             ehResult = OC_EH_ERROR;
187                         }
188                         OCPlatform::sendResponse(pResponse);
189                     }
190                     else
191                     {
192                         std::cout <<"DeviceResource unsupported request type "
193                         << request->getRequestType() << std::endl;
194                         pResponse->setResponseResult(OC_EH_ERROR);
195                         OCPlatform::sendResponse(pResponse);
196                         ehResult = OC_EH_ERROR;
197                     }
198                 }
199                 else
200                 {
201                     std::cout << "DeviceResource unsupported request flag" <<std::endl;
202                 }
203             }
204             else
205             {
206                 std::cout << "Unsupported/invalid header options/values" << std::endl;
207             }
208         }
209
210         return ehResult;
211     }
212
213     virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
214     {
215         OCEntityHandlerResult ehResult = OC_EH_ERROR;
216         if(request)
217         {
218             std::cout << "In Default Entity Handler, uri received: "
219                         << request->getResourceUri() << std::endl;
220
221             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
222             {
223                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
224                 pResponse->setRequestHandle(request->getRequestHandle());
225                 pResponse->setResourceHandle(request->getResourceHandle());
226
227                 if(request->getRequestType() == "GET")
228                 {
229                     std::cout<<"Default Entity Handler: Get Request"<<std::endl;
230                     pResponse->setErrorCode(200);
231                     pResponse->setResourceRepresentation(get(), "");
232                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
233                     {
234                         ehResult = OC_EH_OK;
235                     }
236                 }
237                 else
238                 {
239                     std::cout <<"Default Entity Handler: unsupported request type "
240                     << request->getRequestType() << std::endl;
241                     pResponse->setResponseResult(OC_EH_ERROR);
242                     OCPlatform::sendResponse(pResponse);
243                     ehResult = OC_EH_ERROR;
244                 }
245             }
246             else
247             {
248                 std::cout << "Default Entity Handler: unsupported request flag" <<std::endl;
249             }
250         }
251
252         return ehResult;
253    }
254
255 };
256
257 class LightResource : public Resource
258 {
259     public:
260     LightResource() : m_isOn(false)
261     {
262         std::string resourceURI = "/light";
263         std::string resourceTypeName = "intel.fridge.light";
264         std::string resourceInterface = DEFAULT_INTERFACE;
265         EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
266         uint8_t resourceProperty = 0;
267         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
268             resourceURI,
269             resourceTypeName,
270             resourceInterface,
271             cb,
272             resourceProperty);
273
274         if(OC_STACK_OK != result)
275         {
276             throw std::runtime_error(
277                 std::string("Light Resource failed to start")+std::to_string(result));
278         }
279     }
280     private:
281     OCRepresentation get()
282     {
283         m_rep.setValue("on", m_isOn);
284         return m_rep;
285     }
286
287     void put(const OCRepresentation& rep)
288     {
289         rep.getValue("on", m_isOn);
290     }
291
292     bool m_isOn;
293     protected:
294     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
295     {
296         OCEntityHandlerResult ehResult = OC_EH_ERROR;
297         if(request)
298         {
299             std::cout << "In entity handler for Light, URI is : "
300                       << request->getResourceUri() << std::endl;
301
302             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
303             {
304                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
305                 pResponse->setRequestHandle(request->getRequestHandle());
306                 pResponse->setResourceHandle(request->getResourceHandle());
307
308                 if(request->getRequestType() == "GET")
309                 {
310                     std::cout<<"Light Get Request"<<std::endl;
311                     pResponse->setErrorCode(200);
312                     pResponse->setResourceRepresentation(get(), "");
313                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
314                     {
315                         ehResult = OC_EH_OK;
316                     }
317                 }
318                 else if(request->getRequestType() == "PUT")
319                 {
320                     std::cout <<"Light Put Request"<<std::endl;
321                     put(request->getResourceRepresentation());
322                     pResponse->setErrorCode(200);
323                     pResponse->setResourceRepresentation(get(), "");
324                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
325                     {
326                         ehResult = OC_EH_OK;
327                     }
328                 }
329                 else
330                 {
331                     std::cout << "Light unsupported request type"
332                     << request->getRequestType() << std::endl;
333                     pResponse->setResponseResult(OC_EH_ERROR);
334                     OCPlatform::sendResponse(pResponse);
335                     ehResult = OC_EH_ERROR;
336                 }
337             }
338             else
339             {
340                 std::cout << "Light unsupported request flag" <<std::endl;
341             }
342         }
343
344         return ehResult;
345     }
346 };
347
348 class DoorResource : public Resource
349 {
350     public:
351     DoorResource(const std::string& side):m_isOpen{false}, m_side(side)
352     {
353
354         std::string resourceURI = "/door/"+ side;
355         std::string resourceTypeName = "intel.fridge.door";
356         std::string resourceInterface = DEFAULT_INTERFACE;
357         EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
358
359         uint8_t resourceProperty = 0;
360         OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
361             resourceURI,
362             resourceTypeName,
363             resourceInterface,
364             cb,
365             resourceProperty);
366
367         if(OC_STACK_OK != result)
368         {
369             throw std::runtime_error(
370                 std::string("Door Resource failed to start")+std::to_string(result));
371         }
372     }
373
374     private:
375     OCRepresentation get()
376     {
377         m_rep.setValue("open", m_isOpen);
378         m_rep.setValue("side", m_side);
379         return m_rep;
380     }
381
382     void put(const OCRepresentation& rep)
383     {
384         rep.getValue("open", m_isOpen);
385         // Note, we won't let the user change the door side!
386     }
387     bool m_isOpen;
388     std::string m_side;
389     protected:
390     virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
391     {
392         std::cout << "EH of door invoked " << std::endl;
393         OCEntityHandlerResult ehResult = OC_EH_ERROR;
394
395         if(request)
396         {
397             std::cout << "In entity handler for Door, URI is : "
398                       << request->getResourceUri() << std::endl;
399
400             if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
401             {
402                 auto pResponse = std::make_shared<OC::OCResourceResponse>();
403                 pResponse->setRequestHandle(request->getRequestHandle());
404                 pResponse->setResourceHandle(request->getResourceHandle());
405
406                 if(request->getRequestType() == "GET")
407                 {
408                     // note that we know the side because std::bind gives us the
409                     // appropriate object
410                     std::cout<< m_side << " Door Get Request"<<std::endl;
411                     pResponse->setErrorCode(200);
412                     pResponse->setResourceRepresentation(get(), "");
413                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
414                     {
415                         ehResult = OC_EH_OK;
416                     }
417                 }
418                 else if(request->getRequestType() == "PUT")
419                 {
420                     std::cout << m_side <<" Door Put Request"<<std::endl;
421                     put(request->getResourceRepresentation());
422                     pResponse->setErrorCode(200);
423                     pResponse->setResourceRepresentation(get(),"");
424                     if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
425                     {
426                         ehResult = OC_EH_OK;
427                     }
428                 }
429                 else
430                 {
431                     std::cout <<m_side<<" Door unsupported request type "
432                     << request->getRequestType() << std::endl;
433                     pResponse->setResponseResult(OC_EH_ERROR);
434                     OCPlatform::sendResponse(pResponse);
435                     ehResult = OC_EH_ERROR;
436                 }
437             }
438             else
439             {
440                 std::cout << "Door unsupported request flag" <<std::endl;
441             }
442         }
443
444         return ehResult;
445     }
446
447 };
448
449 class Refrigerator
450 {
451     public:
452     Refrigerator()
453         :
454         m_light(),
455         m_device(),
456         m_leftdoor("left"),
457         m_rightdoor("right")
458     {
459     }
460     private:
461     LightResource m_light;
462     DeviceResource m_device;
463     DoorResource m_leftdoor;
464     DoorResource m_rightdoor;
465 };
466
467 int main ()
468 {
469     PlatformConfig cfg
470     {
471         ServiceType::InProc,
472         ModeType::Server,
473         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
474         0,         // Uses randomly available port
475         QualityOfService::LowQos
476     };
477
478     OCPlatform::Configure(cfg);
479     Refrigerator rf;
480
481     // we will keep the server alive for at most 30 minutes
482     std::this_thread::sleep_for(std::chrono::minutes(30));
483     return 0;
484 }
485