1 //******************************************************************
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
6 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
12 // http://www.apache.org/licenses/LICENSE-2.0
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
20 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
32 #include "oic_malloc.h"
35 #include "ocpayload.h"
39 #define VERIFY_SUCCESS(op) \
41 if (op != OC_STACK_OK) \
43 cout << #op << " failed!!" << endl; \
48 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
50 const int URI_MAXSIZE = 19;
52 static int gObserveNotifyType = 3;
55 int gLightUnderObservation = 0;
57 static GMainLoop *g_mainloop = NULL;
60 static LightResource Light;
61 // This variable determines instance number of the Light resource.
62 // Used by POST method to create a new instance of Light resource.
63 static int gCurrLightInstance = 0;
65 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
67 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
70 static int stopPresenceCount = 10;
71 #define numPresenceResources (2)
74 char *gResourceUri= (char *)"/a/light";
75 const char *dateOfManufacture = "2016-01-15";
76 const char *deviceName = "myDeviceName";
77 const char *deviceUUID = "51b55ddc-ccbb-4cb3-a57f-494eeca13a21";
78 const char *firmwareVersion = "myFirmwareVersion";
79 const char *manufacturerName = "myName";
80 const char *operatingSystemVersion = "myOS";
81 const char *hardwareVersion = "myHardwareVersion";
82 const char *platformID = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
83 const char *protocolIndependentID = "45a908e9-c06c-4935-b2dd-4195da863a11";
84 const char *manufacturerLink = "https://www.iotivity.org";
85 const char *modelNumber = "myModelNumber";
86 const char *platformVersion = "myPlatformVersion";
87 const char *supportLink = "https://www.iotivity.org";
88 const char *version = "myVersion";
89 const char *systemTime = "2015-05-15T11.04";
90 const char *specVersion = "core.1.1.0";
91 const char *dataModelVersions = "res.1.1.0,sh.1.1.0";
92 const char *deviceType = "oic.d.tv";
94 // Entity handler should check for resourceTypeName and ResourceInterface in order to GET
95 // the existence of a known resource
96 const char *resourceTypeName = "core.light";
97 const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
99 OCPlatformInfo platformInfo;
101 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
103 OCRepPayload* payload = OCRepPayloadCreate();
106 cout << "Failed to allocate Payload";
110 OCRepPayloadSetUri(payload, uri);
111 OCRepPayloadSetPropBool(payload, "state", state);
112 OCRepPayloadSetPropInt(payload, "power", power);
117 //This function takes the request as an input and returns the response
118 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
120 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
122 cout << "Incoming payload not a representation";
126 OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
128 LightResource *currLightResource = &Light;
130 if (ehRequest->resource == gLightInstance[0].handle)
132 currLightResource = &gLightInstance[0];
133 gResourceUri = (char *) "a/light/0";
135 else if (ehRequest->resource == gLightInstance[1].handle)
137 currLightResource = &gLightInstance[1];
138 gResourceUri = (char *) "a/light/1";
141 if(OC_REST_PUT == ehRequest->method)
143 // Get pointer to query
145 if(OCRepPayloadGetPropInt(input, "power", &pow))
147 currLightResource->power =pow;
151 if(OCRepPayloadGetPropBool(input, "state", &state))
153 currLightResource->state = state;
157 return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
161 * Very simple example of query parsing.
162 * The query may have multiple filters separated by ';'.
163 * It is upto the entity handler to parse the query for the individual filters,
164 * VALIDATE them and respond as it sees fit.
166 * This function only returns false if the query is exactly "power<X" and
167 * current power is greater than X. If X cannot be parsed for an int,
170 bool checkIfQueryForPowerPassed(char * query)
172 if (query && strncmp(query, "power<", strlen("power<")) == 0)
174 char * pointerToOperator = strstr(query, "<");
176 if (pointerToOperator)
178 int powerRequested = atoi(pointerToOperator + 1);
179 if (Light.power > powerRequested)
181 cout << "\nCurrent power: "<< Light.power << "Requested: " << powerRequested;
190 * Application should validate and process these as desired.
192 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
194 cout << "\nReceived query %s" << entityHandlerRequest->query;
195 cout << "\nNot processing query";
199 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
200 OCRepPayload **payload)
202 OCEntityHandlerResult ehResult;
203 bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
205 // Empty payload if the query has no match.
208 OCRepPayload *getResp = constructResponse(ehRequest);
211 cout << "\nconstructResponse failed";
226 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
227 OCRepPayload** payload)
229 OCEntityHandlerResult ehResult;
230 OCRepPayload *putResp = constructResponse(ehRequest);
234 cout << "\nFailed to construct response";
244 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
245 OCEntityHandlerResponse *response, OCRepPayload** payload)
247 OCEntityHandlerResult ehResult = OC_EH_OK;
248 OCRepPayload *respPLPost_light = nullptr;
251 * The entity handler determines how to process a POST request.
252 * Per the REST paradigm, POST can also be used to update representation of existing
253 * resource or create a new resource.
254 * In the sample below, if the POST is for /a/light then a new instance of the Light
255 * resource is created with default representation (if representation is included in
256 * POST payload it can be used as initial values) as long as the instance is
257 * lesser than max new instance count. Once max instance count is reached, POST on
258 * /a/light updated the representation of /a/light (just like PUT).
261 if (ehRequest->resource == Light.handle)
263 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
265 // Create new Light instance
266 char newLightUri[URI_MAXSIZE];
267 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
269 respPLPost_light = OCRepPayloadCreate();
270 OCRepPayloadSetUri(respPLPost_light, gResourceUri);
271 OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
273 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
275 cout << "\nCreated new Light instance";
276 gLightInstance[gCurrLightInstance].state = 0;
277 gLightInstance[gCurrLightInstance].power = 0;
278 gCurrLightInstance++;
279 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
280 ehResult = OC_EH_RESOURCE_CREATED;
285 // Update repesentation of /a/light
288 respPLPost_light = constructResponse(ehRequest);
293 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
295 if (ehRequest->resource == gLightInstance[i].handle)
297 gLightInstance[i].state = true;
298 gLightInstance[i].power = 22;
301 respPLPost_light = constructResponse(ehRequest);
306 respPLPost_light = constructResponse(ehRequest);
312 if ((respPLPost_light != NULL))
314 *payload = respPLPost_light;
318 cout << "\n Payload was NULL";
319 ehResult = OC_EH_ERROR;
325 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
327 if(ehRequest == NULL)
329 cout << "\nThe ehRequest is NULL";
332 OCEntityHandlerResult ehResult = OC_EH_OK;
334 cout << "\nExecuting " << __func__ << " for resource " << ehRequest->resource;
337 * In the sample below, the application will:
338 * 1a. pass the delete request to the c stack
339 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
340 * (e.g. send observers notification, remove observers...)
341 * 1c. the c stack returns with the result whether the request is fullfilled.
342 * 2. optionally, app removes observers out of its array 'interestedObservers'
345 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
347 //Step 1: Ask stack to do the work.
348 OCStackResult result = OCDeleteResource(ehRequest->resource);
350 if (result == OC_STACK_OK)
352 cout << "\nDelete Resource operation succeeded.";
355 //Step 2: clear observers who wanted to observe this resource at the app level.
356 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
358 if (interestedObservers[i].resourceHandle == ehRequest->resource)
360 interestedObservers[i].valid = false;
361 interestedObservers[i].observationId = 0;
362 interestedObservers[i].resourceHandle = NULL;
366 else if (result == OC_STACK_NO_RESOURCE)
368 cout << "\nThe resource doesn't exist or it might have been deleted.";
369 ehResult = OC_EH_RESOURCE_DELETED;
373 cout << "\nEncountered error from OCDeleteResource().";
374 ehResult = OC_EH_ERROR;
377 else if (ehRequest->resource != Light.handle)
379 //Let's this app not supporting DELETE on some resources so
380 //consider the DELETE request is received for a non-support resource.
381 cout << "\nThe request is received for a non-support resource.";
382 ehResult = OC_EH_FORBIDDEN;
388 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest)
390 cout << "\nExecuting " << __func__;
392 return OC_EH_RESOURCE_NOT_FOUND;
395 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
397 cout << "\nReceived observation registration request with observation Id "
398 << ehRequest->obsInfo.obsId;
399 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
401 if (interestedObservers[i].valid == false)
403 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
404 interestedObservers[i].valid = true;
405 gLightUnderObservation = 1;
411 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
413 bool clientStillObserving = false;
415 cout << "\nReceived observation deregistration request for observation Id "
416 << ehRequest->obsInfo.obsId;
417 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
419 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
421 interestedObservers[i].valid = false;
423 if (interestedObservers[i].valid == true)
425 // Even if there is one single client observing we continue notifying entity handler
426 clientStillObserving = true;
429 if (clientStillObserving == false)
430 gLightUnderObservation = 0;
433 OCEntityHandlerResult
434 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
435 OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* callbackParam)
437 cout << "\nInside device default entity handler - flags: " << flag << ", uri: %s" << uri;
439 OCEntityHandlerResult ehResult = OC_EH_OK;
440 OCEntityHandlerResponse response;
443 if (!entityHandlerRequest)
445 cout << "\nInvalid request pointer";
448 // Initialize certain response fields
449 response.numSendVendorSpecificHeaderOptions = 0;
450 memset(response.sendVendorSpecificHeaderOptions, 0,
451 sizeof response.sendVendorSpecificHeaderOptions);
452 memset(response.resourceUri, 0, sizeof response.resourceUri);
453 OCRepPayload* payload = nullptr;
456 if (flag & OC_REQUEST_FLAG)
458 cout << "\nFlag includes OC_REQUEST_FLAG";
460 if (entityHandlerRequest->resource == NULL)
462 cout << "\nReceived request from client to a non-existing resource";
463 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
465 else if (OC_REST_GET == entityHandlerRequest->method)
467 cout << "\nReceived OC_REST_GET from client";
468 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
470 else if (OC_REST_PUT == entityHandlerRequest->method)
472 cout << "\nReceived OC_REST_PUT from client";
473 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
475 else if (OC_REST_DELETE == entityHandlerRequest->method)
477 cout << "\nReceived OC_REST_DELETE from client";
478 ehResult = ProcessDeleteRequest (entityHandlerRequest);
482 cout << "\nReceived unsupported method " << entityHandlerRequest->method
484 ehResult = OC_EH_ERROR;
486 // If the result isn't an error or forbidden, send response
487 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
489 // Format the response. Note this requires some info about the request
490 response.requestHandle = entityHandlerRequest->requestHandle;
491 response.resourceHandle = entityHandlerRequest->resource;
492 response.ehResult = ehResult;
493 response.payload = reinterpret_cast<OCPayload*>(payload);
494 // Indicate that response is NOT in a persistent buffer
495 response.persistentBufferFlag = 0;
498 if (OCDoResponse(&response) != OC_STACK_OK)
500 cout << "\nError sending response";
501 ehResult = OC_EH_ERROR;
505 if (flag & OC_OBSERVE_FLAG)
507 cout << "\nFlag includes OC_OBSERVE_FLAG";
508 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
510 cout << "\nReceived OC_OBSERVE_REGISTER from client";
512 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
514 cout << "\nReceived OC_OBSERVE_DEREGISTER from client";
518 OCPayloadDestroy(response.payload);
522 OCEntityHandlerResult
523 OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
524 OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
526 // This is callback is associated with the 2 presence notification
527 // resources. They are non-operational.
531 OCEntityHandlerResult
532 OCEntityHandlerCb (OCEntityHandlerFlag flag,
533 OCEntityHandlerRequest *entityHandlerRequest, void* callback)
535 cout << "\nInside entity handler - flags: " << flag;
537 OCEntityHandlerResult ehResult = OC_EH_OK;
538 OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
541 if (!entityHandlerRequest)
543 cout << "\nInvalid request pointer";
547 // Initialize certain response fields
548 response.numSendVendorSpecificHeaderOptions = 0;
549 memset(response.sendVendorSpecificHeaderOptions,
550 0, sizeof response.sendVendorSpecificHeaderOptions);
551 memset(response.resourceUri, 0, sizeof response.resourceUri);
552 OCRepPayload* payload = nullptr;
554 if (flag & OC_REQUEST_FLAG)
556 cout << "\n=================================\n";
557 cout << "\nFlag includes OC_REQUEST_FLAG\n";
559 if (OC_REST_GET == entityHandlerRequest->method)
561 cout << "\nReceived OC_REST_GET from client";
562 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
563 cout << "\n=================================\n";
565 else if (OC_REST_PUT == entityHandlerRequest->method)
567 cout << "\nReceived OC_REST_PUT from client";
568 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
569 cout << "\n=================================\n";
571 else if (OC_REST_POST == entityHandlerRequest->method)
573 cout << "\nReceived OC_REST_POST from client";
574 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
575 cout << "\n=================================\n";
577 else if (OC_REST_DELETE == entityHandlerRequest->method)
579 cout << "\nReceived OC_REST_DELETE from client";
580 ehResult = ProcessDeleteRequest (entityHandlerRequest);
581 cout << "\n=================================\n";
585 cout << "\nReceived unsupported method " << entityHandlerRequest->method << " from client";
586 ehResult = OC_EH_ERROR;
588 // If the result isn't an error or forbidden, send response
589 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
591 // Format the response. Note this requires some info about the request
592 response.requestHandle = entityHandlerRequest->requestHandle;
593 response.resourceHandle = entityHandlerRequest->resource;
594 response.ehResult = ehResult;
595 response.payload = reinterpret_cast<OCPayload*>(payload);
596 // Indicate that response is NOT in a persistent buffer
597 response.persistentBufferFlag = 0;
599 // Handle vendor specific options
600 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
601 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
603 cout << "\nReceived vendor specific options";
605 OCHeaderOption * rcvdOptions =
606 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
607 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
609 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
611 cout << "\nReceived option with ID " << ((OCHeaderOption)rcvdOptions[i]).optionID;
614 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
615 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
616 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
617 sendOptions[0].protocolID = OC_COAP_ID;
618 sendOptions[0].optionID = 2248;
619 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
620 sendOptions[0].optionLength = 10;
621 sendOptions[1].protocolID = OC_COAP_ID;
622 sendOptions[1].optionID = 2600;
623 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
624 sendOptions[1].optionLength = 10;
625 response.numSendVendorSpecificHeaderOptions = 2;
629 if (OCDoResponse(&response) != OC_STACK_OK)
631 cout << "\nError sending response";
632 ehResult = OC_EH_ERROR;
636 if (flag & OC_OBSERVE_FLAG)
638 cout << "\nFlag includes OC_OBSERVE_FLAG";
640 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
642 cout << "\nReceived OC_OBSERVE_REGISTER from client";
643 ProcessObserveRegister (entityHandlerRequest);
645 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
647 cout << "\nReceived OC_OBSERVE_DEREGISTER from client";
648 ProcessObserveDeregister (entityHandlerRequest);
652 OCPayloadDestroy(response.payload);
656 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
657 void handleSigInt(int signum)
659 if (signum == SIGINT)
665 void *ChangeLightRepresentation (void *param)
668 OCStackResult result = OC_STACK_ERROR;
671 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
672 OCObservationId obsNotify[numNotifies];
678 if (gLightUnderObservation)
680 cout << "\n=====> Notifying stack of new power level" << Light.power;
681 if (gObserveNotifyType == 1)
683 // Notify list of observers. Alternate observers on the list will be notified.
685 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
687 if (interestedObservers[i].valid == true)
689 obsNotify[j] = interestedObservers[i].observationId;
694 OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
695 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
697 OCRepPayloadDestroy(payload);
699 else if (gObserveNotifyType == 0)
701 // Notifying all observers
702 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
703 if (OC_STACK_NO_OBSERVERS == result)
705 cout << "\n=====> No more observers exist, stop sending observations";
706 gLightUnderObservation = 0;
711 cout << "\nIncorrect notification type selected";
715 if(stopPresenceCount > 0)
717 cout << "\n=====> Counting down to stop presence " << stopPresenceCount;
719 if(!stopPresenceCount--)
721 cout << "\n=====> stopping presence";
730 void *presenceNotificationGenerator(void *param)
734 OCDoHandle presenceNotificationHandles[numPresenceResources];
735 OCStackResult res = OC_STACK_OK;
737 std::array<std::string, numPresenceResources> presenceNotificationResources { {
738 std::string("core.fan"),
739 std::string("core.led") } };
740 std::array<std::string, numPresenceResources> presenceNotificationUris { {
741 std::string("/a/fan"),
742 std::string("/a/led") } };
744 for(int i=0; i<numPresenceResources; i++)
746 if(res == OC_STACK_OK)
749 res = OCCreateResource(&presenceNotificationHandles[i],
750 presenceNotificationResources.at(i).c_str(),
751 OC_RSRVD_INTERFACE_DEFAULT,
752 presenceNotificationUris.at(i).c_str(),
753 OCNOPEntityHandlerCb,
755 OC_DISCOVERABLE|OC_OBSERVABLE);
757 if(res != OC_STACK_OK)
759 cout << "\nPresence Notification Generator failed[" << getResult(res)
760 << "] to create resource " << presenceNotificationResources.at(i).c_str();
763 cout << "\nCreated " << presenceNotificationUris[i].c_str() << " for presence notification";
766 for(int i=0; i<numPresenceResources; i++)
768 if(res == OC_STACK_OK)
770 res = OCDeleteResource(presenceNotificationHandles[i]);
772 if(res != OC_STACK_OK)
774 cout << "\nPresence Notification Generator failed to delete resource"
775 << presenceNotificationResources.at(i).c_str();
778 cout << "\nDeleted " << presenceNotificationUris[i].c_str() << " for presence notification";
784 int createLightResource (char *uri, LightResource *lightResource)
788 cout << "\nResource URI cannot be NULL";
792 lightResource->state = false;
793 lightResource->power= 0;
794 OCStackResult res = OCCreateResource(&(lightResource->handle),
800 OC_DISCOVERABLE|OC_OBSERVABLE);
801 cout << "\nCreated Light resource with result " << getResult(res);
806 void DeletePlatformInfo()
808 free (platformInfo.platformID);
809 free (platformInfo.manufacturerName);
810 free (platformInfo.manufacturerUrl);
811 free (platformInfo.modelNumber);
812 free (platformInfo.dateOfManufacture);
813 free (platformInfo.platformVersion);
814 free (platformInfo.operatingSystemVersion);
815 free (platformInfo.hardwareVersion);
816 free (platformInfo.firmwareVersion);
817 free (platformInfo.supportUrl);
818 free (platformInfo.systemTime);
821 bool DuplicateString(char** targetString, const char* sourceString)
829 *targetString = (char *) malloc(strlen(sourceString) + 1);
833 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
840 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
841 const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
842 const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
843 const char *firmwareVersion, const char* supportUrl, const char* systemTime)
848 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_PLATFORM_NAME_LENGTH))
850 return OC_STACK_INVALID_PARAM;
853 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_PLATFORM_URL_LENGTH))
855 return OC_STACK_INVALID_PARAM;
858 if(!DuplicateString(&platformInfo.platformID, platformID))
863 if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
868 if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
873 if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
878 if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
883 if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
888 if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
893 if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
898 if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
903 if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
908 if(!DuplicateString(&platformInfo.systemTime, systemTime))
918 DeletePlatformInfo();
919 return OC_STACK_ERROR;
922 OCStackResult SetDeviceInfo()
924 OCResourceHandle resourceHandle = OCGetResourceHandleAtUri(OC_RSRVD_DEVICE_URI);
925 if (resourceHandle == NULL)
927 OIC_LOG(ERROR, TAG, "Device Resource does not exist.");
931 VERIFY_SUCCESS(OCBindResourceTypeToResource(resourceHandle, deviceType));
932 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, deviceName));
933 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, specVersion));
934 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION,
936 VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_PROTOCOL_INDEPENDENT_ID,
937 protocolIndependentID));
939 OIC_LOG(INFO, TAG, "Device information initialized successfully.");
943 return OC_STACK_ERROR;
946 static void PrintUsage()
948 cout << "\nUsage : ocserver -o <0|1>";
949 cout << "\n-o 0 : Notify all observers";
950 cout << "\n-o 1 : Notify list of observers";
953 void *GMainLoopThread(void *param)
958 if (OCProcess() != OC_STACK_OK)
960 cout << "\nOCStack process error";
963 #ifndef ROUTING_GATEWAY
970 g_main_loop_quit(g_mainloop);
975 int main(int argc, char* argv[])
978 pthread_t threadId_presence;
981 g_mainloop = g_main_loop_new(NULL, FALSE);
984 printf("g_main_loop_new failed\n");
988 while ((opt = getopt(argc, argv, "o:")) != -1)
993 gObserveNotifyType = atoi(optarg);
1001 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
1007 cout << "\nOCServer is starting...";
1009 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1011 cout << "\nOCStack init error";
1015 #ifdef WITH_PRESENCE
1016 if (OCStartPresence(0) != OC_STACK_OK)
1018 cout << "\nOCStack presence/discovery error";
1023 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1025 OCStackResult registrationResult =
1026 SetPlatformInfo(platformID, manufacturerName, manufacturerLink, modelNumber,
1027 dateOfManufacture, platformVersion, operatingSystemVersion, hardwareVersion,
1028 firmwareVersion, supportLink, systemTime);
1030 if (registrationResult != OC_STACK_OK)
1032 cout << "\nPlatform info setting failed locally!";
1033 exit (EXIT_FAILURE);
1036 registrationResult = OCSetPlatformInfo(platformInfo);
1038 if (registrationResult != OC_STACK_OK)
1040 cout << "\nPlatform Registration failed!";
1041 exit (EXIT_FAILURE);
1044 registrationResult = SetDeviceInfo();
1046 if (registrationResult != OC_STACK_OK)
1048 cout << "\nDevice Registration failed!";
1049 exit (EXIT_FAILURE);
1053 * Declare and create the example resource: Light
1055 createLightResource(gResourceUri, &Light);
1057 // Initialize observations data structure for the resource
1058 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1060 interestedObservers[i].valid = false;
1064 * Create a thread for changing the representation of the Light
1066 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
1069 * Create a thread for generating changes that cause presence notifications
1070 * to be sent to clients
1073 #ifdef WITH_PRESENCE
1074 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1077 // Break from loop with Ctrl-C
1078 cout << "\nEntering ocserver main loop...";
1080 DeletePlatformInfo();
1082 signal(SIGINT, handleSigInt);
1084 int result = pthread_create(&g_thread, NULL, GMainLoopThread, (void *)NULL);
1087 printf("pthread_create failed in initialize\n");
1091 g_main_loop_run(g_mainloop);
1094 * Cancel the Light thread and wait for it to terminate
1096 pthread_cancel(threadId);
1097 pthread_join(threadId, NULL);
1098 pthread_cancel(threadId_presence);
1099 pthread_join(threadId_presence, NULL);
1101 cout << "\nExiting ocserver main loop...\n";
1103 if (OCStop() != OC_STACK_OK)
1105 cout << "\nOCStack process error";