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"
34 #include "ocpayload.h"
37 namespace PH = std::placeholders;
39 // Option ID for API version and client token
40 const uint16_t API_VERSION = 2048;
41 const uint16_t TOKEN = 3000;
43 // Setting API version and token (shared out of band with client)
44 // This assumes the fact that this server responds
45 // only with a server with below version and token
46 const std::string FRIDGE_CLIENT_API_VERSION = "v.1.0";
47 const std::string FRIDGE_CLIENT_TOKEN = "21ae43gf";
49 // Set of strings for each of platform Info fields
50 std::string platformId = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
51 std::string manufacturerName = "OCF";
52 std::string manufacturerLink = "https://www.iotivity.org";
53 std::string modelNumber = "myModelNumber";
54 std::string dateOfManufacture = "2016-01-15";
55 std::string platformVersion = "myPlatformVersion";
56 std::string operatingSystemVersion = "myOS";
57 std::string hardwareVersion = "myHardwareVersion";
58 std::string firmwareVersion = "1.0";
59 std::string supportLink = "https://www.iotivity.org";
60 std::string systemTime = "2016-01-15T11.01";
62 // Set of strings for each of device info fields
63 std::string deviceName = "IoTivity Fridge Server";
64 std::string specVersion = "core.1.1.0";
65 std::vector<std::string> dataModelVersions = {"res.1.1.0"};
66 std::string protocolIndependentID = "054718eb-b1e7-4e9e-9892-30e718a6a8f3";
68 // OCPlatformInfo Contains all the platform info to be stored
69 OCPlatformInfo platformInfo;
74 OCResourceHandle m_resourceHandle;
75 OCRepresentation m_rep;
76 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)=0;
79 class DeviceResource : public Resource
83 DeviceResource():m_modelName{}
85 std::string resourceURI = "/device";
86 std::string resourceTypeName = "intel.fridge";
87 std::string resourceInterface = DEFAULT_INTERFACE;
88 EntityHandler cb = std::bind(&DeviceResource::entityHandler, this,PH::_1);
90 EntityHandler defaultEH = std::bind(&DeviceResource::defaultEntityHandler
93 std::cout << "Setting device default entity handler\n";
94 OCPlatform::setDefaultDeviceEntityHandler(defaultEH);
96 uint8_t resourceProperty = OC_DISCOVERABLE;
97 OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
104 if(OC_STACK_OK != result)
106 throw std::runtime_error(
107 std::string("Device Resource failed to start")+std::to_string(result));
111 OCRepresentation get()
113 m_rep.setValue("device_name", std::string("Intel Powered 2 door, 1 light refrigerator"));
117 OCStackResult deleteDeviceResource()
119 OCStackResult result = OCPlatform::unregisterResource(m_resourceHandle);
120 if(OC_STACK_OK != result)
122 throw std::runtime_error(
123 std::string("Device Resource failed to unregister/delete") + std::to_string(result));
128 std::string m_modelName;
130 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
132 OCEntityHandlerResult ehResult = OC_EH_ERROR;
135 // Get the header options from the request
136 HeaderOptions headerOptions = request->getHeaderOptions();
137 std::string clientAPIVersion;
138 std::string clientToken;
140 // Get the message ID from the request
141 std::cout << " MessageID: " << request->getMessageID() << std::endl;
143 // Search the header options map and look for API version and Client token
144 for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
146 uint16_t optionID = it->getOptionID();
147 if(optionID == API_VERSION)
149 clientAPIVersion = it->getOptionData();
150 std::cout << " Client API version: " << clientAPIVersion << std::endl;
152 else if(optionID == TOKEN)
154 clientToken = it->getOptionData();
155 std::cout << " Client token: " << clientToken << std::endl;
159 std::cout << " Invalid header option " << std::endl;
163 // In this case Server entity handler verifies API version
164 // and client token. If they are valid, client requests are handled.
165 if(clientAPIVersion == FRIDGE_CLIENT_API_VERSION && clientToken == FRIDGE_CLIENT_TOKEN)
167 HeaderOptions serverHeaderOptions;
170 // Set API version from server side
171 HeaderOption::OCHeaderOption apiVersion(API_VERSION, FRIDGE_CLIENT_API_VERSION);
172 serverHeaderOptions.push_back(apiVersion);
174 catch(OCException& e)
176 std::cout << "Error creating HeaderOption in server: " << e.what() << std::endl;
179 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
181 auto pResponse = std::make_shared<OC::OCResourceResponse>();
182 pResponse->setRequestHandle(request->getRequestHandle());
183 pResponse->setResourceHandle(request->getResourceHandle());
184 pResponse->setHeaderOptions(serverHeaderOptions);
186 if(request->getRequestType() == "GET")
188 std::cout<<"DeviceResource Get Request"<<std::endl;
190 pResponse->setResponseResult(OC_EH_OK);
191 pResponse->setResourceRepresentation(get(), "");
192 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
197 else if(request->getRequestType() == "DELETE")
199 std::cout<<"DeviceResource Delete Request"<<std::endl;
200 if(deleteDeviceResource() == OC_STACK_OK)
203 pResponse->setResponseResult(OC_EH_RESOURCE_DELETED);
208 pResponse->setResponseResult(OC_EH_ERROR);
209 ehResult = OC_EH_ERROR;
211 OCPlatform::sendResponse(pResponse);
215 std::cout <<"DeviceResource unsupported request type "
216 << request->getRequestType() << std::endl;
217 pResponse->setResponseResult(OC_EH_ERROR);
218 OCPlatform::sendResponse(pResponse);
219 ehResult = OC_EH_ERROR;
224 std::cout << "DeviceResource unsupported request flag" <<std::endl;
229 std::cout << "Unsupported/invalid header options/values" << std::endl;
236 virtual OCEntityHandlerResult defaultEntityHandler(std::shared_ptr<OCResourceRequest> request)
238 OCEntityHandlerResult ehResult = OC_EH_ERROR;
241 std::cout << "In Default Entity Handler, uri received: "
242 << request->getResourceUri() << std::endl;
244 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
246 auto pResponse = std::make_shared<OC::OCResourceResponse>();
247 pResponse->setRequestHandle(request->getRequestHandle());
248 pResponse->setResourceHandle(request->getResourceHandle());
250 if(request->getRequestType() == "GET")
252 std::cout<<"Default Entity Handler: Get Request"<<std::endl;
254 pResponse->setResourceRepresentation(get(), "");
255 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
262 std::cout <<"Default Entity Handler: unsupported request type "
263 << request->getRequestType() << std::endl;
264 pResponse->setResponseResult(OC_EH_ERROR);
265 OCPlatform::sendResponse(pResponse);
266 ehResult = OC_EH_ERROR;
271 std::cout << "Default Entity Handler: unsupported request flag" <<std::endl;
280 class LightResource : public Resource
283 LightResource() : m_isOn(false)
285 std::string resourceURI = "/light";
286 std::string resourceTypeName = "intel.fridge.light";
287 std::string resourceInterface = DEFAULT_INTERFACE;
288 EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1);
289 uint8_t resourceProperty = 0;
290 OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
297 if(OC_STACK_OK != result)
299 throw std::runtime_error(
300 std::string("Light Resource failed to start")+std::to_string(result));
304 OCRepresentation get()
306 m_rep.setValue("on", m_isOn);
310 void put(const OCRepresentation& rep)
312 rep.getValue("on", m_isOn);
317 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
319 OCEntityHandlerResult ehResult = OC_EH_ERROR;
322 std::cout << "In entity handler for Light, URI is : "
323 << request->getResourceUri() << std::endl;
325 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
327 auto pResponse = std::make_shared<OC::OCResourceResponse>();
328 pResponse->setRequestHandle(request->getRequestHandle());
329 pResponse->setResourceHandle(request->getResourceHandle());
331 if(request->getRequestType() == "GET")
333 std::cout<<"Light Get Request"<<std::endl;
335 pResponse->setResourceRepresentation(get(), "");
336 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
341 else if(request->getRequestType() == "PUT")
343 std::cout <<"Light Put Request"<<std::endl;
344 put(request->getResourceRepresentation());
346 pResponse->setResourceRepresentation(get(), "");
347 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
354 std::cout << "Light unsupported request type"
355 << request->getRequestType() << std::endl;
356 pResponse->setResponseResult(OC_EH_ERROR);
357 OCPlatform::sendResponse(pResponse);
358 ehResult = OC_EH_ERROR;
363 std::cout << "Light unsupported request flag" <<std::endl;
371 class DoorResource : public Resource
374 DoorResource(const std::string& side):m_isOpen{false}, m_side(side)
377 std::string resourceURI = "/door/"+ side;
378 std::string resourceTypeName = "intel.fridge.door";
379 std::string resourceInterface = DEFAULT_INTERFACE;
380 EntityHandler cb = std::bind(&DoorResource::entityHandler, this,PH::_1);
382 uint8_t resourceProperty = 0;
383 OCStackResult result = OCPlatform::registerResource(m_resourceHandle,
390 if(OC_STACK_OK != result)
392 throw std::runtime_error(
393 std::string("Door Resource failed to start")+std::to_string(result));
398 OCRepresentation get()
400 m_rep.setValue("open", m_isOpen);
401 m_rep.setValue("side", m_side);
405 void put(const OCRepresentation& rep)
407 rep.getValue("open", m_isOpen);
408 // Note, we won't let the user change the door side!
413 virtual OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
415 std::cout << "EH of door invoked " << std::endl;
416 OCEntityHandlerResult ehResult = OC_EH_ERROR;
420 std::cout << "In entity handler for Door, URI is : "
421 << request->getResourceUri() << std::endl;
423 if(request->getRequestHandlerFlag() == RequestHandlerFlag::RequestFlag)
425 auto pResponse = std::make_shared<OC::OCResourceResponse>();
426 pResponse->setRequestHandle(request->getRequestHandle());
427 pResponse->setResourceHandle(request->getResourceHandle());
429 if(request->getRequestType() == "GET")
431 // note that we know the side because std::bind gives us the
432 // appropriate object
433 std::cout<< m_side << " Door Get Request"<<std::endl;
435 pResponse->setResourceRepresentation(get(), "");
436 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
441 else if(request->getRequestType() == "PUT")
443 std::cout << m_side <<" Door Put Request"<<std::endl;
444 put(request->getResourceRepresentation());
446 pResponse->setResourceRepresentation(get(),"");
447 if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
454 std::cout <<m_side<<" Door unsupported request type "
455 << request->getRequestType() << std::endl;
456 pResponse->setResponseResult(OC_EH_ERROR);
457 OCPlatform::sendResponse(pResponse);
458 ehResult = OC_EH_ERROR;
463 std::cout << "Door unsupported request flag" <<std::endl;
484 LightResource m_light;
485 DeviceResource m_device;
486 DoorResource m_leftdoor;
487 DoorResource m_rightdoor;
490 void DeletePlatformInfo()
492 delete[] platformInfo.platformID;
493 delete[] platformInfo.manufacturerName;
494 delete[] platformInfo.manufacturerUrl;
495 delete[] platformInfo.modelNumber;
496 delete[] platformInfo.dateOfManufacture;
497 delete[] platformInfo.platformVersion;
498 delete[] platformInfo.operatingSystemVersion;
499 delete[] platformInfo.hardwareVersion;
500 delete[] platformInfo.firmwareVersion;
501 delete[] platformInfo.supportUrl;
502 delete[] platformInfo.systemTime;
505 void DuplicateString(char ** targetString, std::string sourceString)
507 *targetString = new char[sourceString.length() + 1];
508 strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1));
511 OCStackResult SetPlatformInfo(std::string platformID, std::string manufacturerName,
512 std::string manufacturerUrl, std::string modelNumber, std::string dateOfManufacture,
513 std::string platformVersion, std::string operatingSystemVersion, std::string hardwareVersion,
514 std::string firmwareVersion, std::string supportUrl, std::string systemTime)
516 DuplicateString(&platformInfo.platformID, platformID);
517 DuplicateString(&platformInfo.manufacturerName, manufacturerName);
518 DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl);
519 DuplicateString(&platformInfo.modelNumber, modelNumber);
520 DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture);
521 DuplicateString(&platformInfo.platformVersion, platformVersion);
522 DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion);
523 DuplicateString(&platformInfo.hardwareVersion, hardwareVersion);
524 DuplicateString(&platformInfo.firmwareVersion, firmwareVersion);
525 DuplicateString(&platformInfo.supportUrl, supportUrl);
526 DuplicateString(&platformInfo.systemTime, systemTime);
531 OCStackResult SetDeviceInfo()
533 OCStackResult result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME,
535 if (result != OC_STACK_OK)
537 std::cout << "Failed to set device name" << std::endl;
541 result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
543 if (result != OC_STACK_OK)
545 std::cout << "Failed to set data model versions" << std::endl;
549 result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, specVersion);
550 if (result != OC_STACK_OK)
552 std::cout << "Failed to set spec version" << std::endl;
556 result = OCPlatform::setPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID,
557 protocolIndependentID);
558 if (result != OC_STACK_OK)
560 std::cout << "Failed to set piid" << std::endl;
573 "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
574 0, // Uses randomly available port
575 QualityOfService::LowQos
578 OCPlatform::Configure(cfg);
581 std::cout << "Starting server & setting platform info\n";
583 OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink,
584 modelNumber, dateOfManufacture, platformVersion, operatingSystemVersion,
585 hardwareVersion, firmwareVersion, supportLink, systemTime);
587 result = OCPlatform::registerPlatformInfo(platformInfo);
589 if (result != OC_STACK_OK)
591 std::cout << "Platform Registration failed\n";
595 result = SetDeviceInfo();
597 if (result != OC_STACK_OK)
599 std::cout << "Device Registration failed\n";
603 DeletePlatformInfo();
604 // we will keep the server alive for at most 30 minutes
605 std::this_thread::sleep_for(std::chrono::minutes(30));