1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
32 #include "OCPlatform.h"
36 namespace PH = std::placeholders;
38 // Option ID for API version and client token
39 const uint16_t API_VERSION = 2048;
40 const uint16_t TOKEN = 3000;
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";
51 OCResourceHandle m_resourceHandle;
52 OCRepresentation m_rep;
53 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)=0;
56 class DeviceResource : public Resource
60 DeviceResource():m_modelName{}
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);
67 EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
70 std::cout << "Setting device default entity handler\n";
71 OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
73 uint8_t resourceProperty = OC_DISCOVERABLE;
74 OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
81 if(OC_STACK_OK != result)
83 throw std::runtime_error(
84 std::string("Device Resource failed to start")+std::to_string(result));
88 OCRepresentation get()
90 m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
94 OCStackResult deleteDeviceResource()
96 OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
97 if(OC_STACK_OK != result)
99 throw std::runtime_error(
100 std::string("Device Resource failed to unregister/delete") + std::to_string(result));
105 std::string m_modelName;
107 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
109 OCEntityHandlerResult ehResult = OC_EH_ERROR;
112 // Get the header options from the request
113 HeaderOptions headerOptions = request->getHeaderOptions();
114 std::string clientAPIVersion;
115 std::string clientToken;
117 // Get the message ID from the request
118 std::cout << " MessageID: " << request->getMessageID() << std::endl;
120 // Search the header options map and look for API version and Client token
121 for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
123 uint16_t optionID = it->getOptionID();
124 if(optionID == API_VERSION)
126 clientAPIVersion = it->getOptionData();
127 std::cout << " Client API version: " << clientAPIVersion << std::endl;
129 else if(optionID == TOKEN)
131 clientToken = it->getOptionData();
132 std::cout << " Client token: " << clientToken << std::endl;
136 std::cout << " Invalid header option " << std::endl;
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)
144 HeaderOptions serverHeaderOptions;
147 // Set API version from server side
148 HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION);
149 serverHeaderOptions.push_back(apiVersion);
151 catch(OCException& e)
153 std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl;
156 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
158 auto pResponse = std::make_shared<OC::OCResourceResponse>();
159 pResponse->setRequestHandle(request->getRequestHandle());
160 pResponse->setResourceHandle(request->getResourceHandle());
161 pResponse->setHeaderOptions(serverHeaderOptions);
163 if(request->getRequestType() == "GET")
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))
174 else if(request->getRequestType() == "DELETE")
176 std::cout<<"DeviceResource Delete Request"<<std::endl;
177 if(deleteDeviceResource() == OC_STACK_OK)
179 pResponse->setErrorCode(200);
180 pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
185 pResponse->setResponseResult(OC_EH_ERROR);
186 ehResult = OC_EH_ERROR;
188 OCPlatform::sendResponse(pResponse);
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;
201 std::cout << "DeviceResource unsupported request flag" <<std::endl;
206 std::cout << "Unsupported/invalid header options/values" << std::endl;
213 virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
215 OCEntityHandlerResult ehResult = OC_EH_ERROR;
218 std::cout << "In Default Entity Handler, uri received: "
219 << request->getResourceUri() << std::endl;
221 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
223 auto pResponse = std::make_shared<OC::OCResourceResponse>();
224 pResponse->setRequestHandle(request->getRequestHandle());
225 pResponse->setResourceHandle(request->getResourceHandle());
227 if(request->getRequestType() == "GET")
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))
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;
248 std::cout << "Default Entity Handler: unsupported request flag" <<std::endl;
257 class LightResource : public Resource
260 LightResource() : m_isOn(false)
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,
274 if(OC_STACK_OK != result)
276 throw std::runtime_error(
277 std::string("Light Resource failed to start")+std::to_string(result));
281 OCRepresentation get()
283 m_rep.setValue("on", m_isOn);
287 void put(const OCRepresentation& rep)
289 rep.getValue("on", m_isOn);
294 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
296 OCEntityHandlerResult ehResult = OC_EH_ERROR;
299 std::cout << "In entity handler for Light, URI is : "
300 << request->getResourceUri() << std::endl;
302 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
304 auto pResponse = std::make_shared<OC::OCResourceResponse>();
305 pResponse->setRequestHandle(request->getRequestHandle());
306 pResponse->setResourceHandle(request->getResourceHandle());
308 if(request->getRequestType() == "GET")
310 std::cout<<"Light Get Request"<<std::endl;
311 pResponse->setErrorCode(200);
312 pResponse->setResourceRepresentation(get(), "");
313 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
318 else if(request->getRequestType() == "PUT")
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))
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;
340 std::cout << "Light unsupported request flag" <<std::endl;
348 class DoorResource : public Resource
351 DoorResource(const std::string& side):m_isOpen{false}, m_side(side)
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);
359 uint8_t resourceProperty = 0;
360 OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
367 if(OC_STACK_OK != result)
369 throw std::runtime_error(
370 std::string("Door Resource failed to start")+std::to_string(result));
375 OCRepresentation get()
377 m_rep.setValue("open", m_isOpen);
378 m_rep.setValue("side", m_side);
382 void put(const OCRepresentation& rep)
384 rep.getValue("open", m_isOpen);
385 // Note, we won't let the user change the door side!
390 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
392 std::cout << "EH of door invoked " << std::endl;
393 OCEntityHandlerResult ehResult = OC_EH_ERROR;
397 std::cout << "In entity handler for Door, URI is : "
398 << request->getResourceUri() << std::endl;
400 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
402 auto pResponse = std::make_shared<OC::OCResourceResponse>();
403 pResponse->setRequestHandle(request->getRequestHandle());
404 pResponse->setResourceHandle(request->getResourceHandle());
406 if(request->getRequestType() == "GET")
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))
418 else if(request->getRequestType() == "PUT")
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))
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;
440 std::cout << "Door unsupported request flag" <<std::endl;
461 LightResource m_light;
462 DeviceResource m_device;
463 DoorResource m_leftdoor;
464 DoorResource m_rightdoor;
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
478 OCPlatform::Configure(cfg);
481 // we will keep the server alive for at most 30 minutes
482 std::this_thread::sleep_for(std::chrono::minutes(30));