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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
35 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
37 const int URI_MAXSIZE = 19;
39 static int gObserveNotifyType = 3;
42 int gLightUnderObservation = 0;
44 static LightResource Light;
45 // This variable determines instance number of the Light resource.
46 // Used by POST method to create a new instance of Light resource.
47 static int gCurrLightInstance = 0;
49 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
51 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
54 static int stopPresenceCount = 10;
55 #define numPresenceResources (2)
58 //TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
59 const char responsePayloadDeleteOk[] =
60 "{App determines payload: Delete Resource operation succeeded.}";
61 const char responsePayloadDeleteNotOK[] =
62 "{App determines payload: Delete Resource operation failed.}";
63 const char responsePayloadResourceDoesNotExist[] =
64 "{App determines payload: The resource does not exist.}";
65 const char responsePayloadDeleteResourceNotSupported[] =
66 "{App determines payload: The request is received for a non-support resource.}";
69 char *gResourceUri= (char *)"/a/light";
70 const char *contentType = "myContentType";
71 const char *dateOfManufacture = "myDateOfManufacture";
72 const char *deviceName = "myDeviceName";
73 const char *deviceUUID = "myDeviceUUID";
74 const char *firmwareVersion = "myFirmwareVersion";
75 const char *hostName = "myHostName";
76 const char *manufacturerName = "myManufacturerNa";
77 const char *manufacturerUrl = "myManufacturerUrl";
78 const char *modelNumber = "myModelNumber";
79 const char *platformVersion = "myPlatformVersion";
80 const char *supportUrl = "mySupportUrl";
81 const char *version = "myVersion";
83 OCDeviceInfo deviceInfo;
85 //This function takes the request as an input and returns the response
87 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
89 cJSON *json = cJSON_CreateObject();
92 LightResource *currLightResource = &Light;
94 if (ehRequest->resource == gLightInstance[0].handle)
96 currLightResource = &gLightInstance[0];
97 gResourceUri = (char *) "a/light/0";
99 else if (ehRequest->resource == gLightInstance[1].handle)
101 currLightResource = &gLightInstance[1];
102 gResourceUri = (char *) "a/light/1";
105 if(OC_REST_PUT == ehRequest->method)
107 cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
108 currLightResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring,
110 currLightResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
111 cJSON_Delete(putJson);
114 cJSON_AddStringToObject(json,"href",gResourceUri);
115 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
116 cJSON_AddStringToObject(format, "state", (char *) (currLightResource->state ? "on":"off"));
117 cJSON_AddNumberToObject(format, "power", currLightResource->power);
119 jsonResponse = cJSON_Print(json);
125 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
126 char *payload, uint16_t maxPayloadSize)
128 OCEntityHandlerResult ehResult;
129 char *getResp = constructJsonResponse(ehRequest);
131 if (maxPayloadSize > strlen ((char *)getResp))
133 strncpy(payload, getResp, strlen((char *)getResp));
138 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
140 ehResult = OC_EH_ERROR;
148 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
149 char *payload, uint16_t maxPayloadSize)
151 OCEntityHandlerResult ehResult;
152 char *putResp = constructJsonResponse(ehRequest);
154 if (maxPayloadSize > strlen ((char *)putResp))
156 strncpy(payload, putResp, strlen((char *)putResp));
161 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
163 ehResult = OC_EH_ERROR;
171 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
172 OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
174 OCEntityHandlerResult ehResult = OC_EH_OK;
175 char *respPLPost_light = NULL;
180 * The entity handler determines how to process a POST request.
181 * Per the REST paradigm, POST can also be used to update representation of existing
182 * resource or create a new resource.
183 * In the sample below, if the POST is for /a/light then a new instance of the Light
184 * resource is created with default representation (if representation is included in
185 * POST payload it can be used as initial values) as long as the instance is
186 * lesser than max new instance count. Once max instance count is reached, POST on
187 * /a/light updated the representation of /a/light (just like PUT)
190 if (ehRequest->resource == Light.handle)
192 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
194 // Create new Light instance
195 char newLightUri[URI_MAXSIZE];
196 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
198 json = cJSON_CreateObject();
199 cJSON_AddStringToObject(json,"href",gResourceUri);
200 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
201 cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
203 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
205 OC_LOG (INFO, TAG, "Created new Light instance\n");
206 gLightInstance[gCurrLightInstance].state = 0;
207 gLightInstance[gCurrLightInstance].power = 0;
208 gCurrLightInstance++;
209 respPLPost_light = cJSON_Print(json);
210 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
211 ehResult = OC_EH_RESOURCE_CREATED;
218 // Update repesentation of /a/light
221 respPLPost_light = constructJsonResponse(ehRequest);
226 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
228 if (ehRequest->resource == gLightInstance[i].handle)
230 gLightInstance[i].state = true;
231 gLightInstance[i].power = 22;
234 respPLPost_light = constructJsonResponse(ehRequest);
239 respPLPost_light = constructJsonResponse(ehRequest);
245 if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
247 strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
251 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
253 ehResult = OC_EH_ERROR;
256 free(respPLPost_light);
260 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
261 char *payload, uint16_t maxPayloadSize)
263 if(ehRequest == NULL)
265 OC_LOG(INFO, TAG, "The ehRequest is NULL");
268 OCEntityHandlerResult ehResult = OC_EH_OK;
270 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
273 * In the sample below, the application will:
274 * 1a. pass the delete request to the c stack
275 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
276 * (e.g. send observers notification, remove observers...)
277 * 1c. the c stack returns with the result whether the request is fullfilled.
278 * 2. optionally, app removes observers out of its array 'interestedObservers'
281 const char* deleteResponse = NULL;
283 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
285 //Step 1: Ask stack to do the work.
286 OCStackResult result = OCDeleteResource(ehRequest->resource);
288 if (result == OC_STACK_OK)
290 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
292 deleteResponse = responsePayloadDeleteOk;
294 //Step 2: clear observers who wanted to observe this resource at the app level.
295 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
297 if (interestedObservers[i].resourceHandle == ehRequest->resource)
299 interestedObservers[i].valid = false;
300 interestedObservers[i].observationId = 0;
301 interestedObservers[i].resourceHandle = NULL;
305 else if (result == OC_STACK_NO_RESOURCE)
307 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
308 deleteResponse = responsePayloadResourceDoesNotExist;
309 ehResult = OC_EH_RESOURCE_DELETED;
313 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
314 deleteResponse = responsePayloadDeleteNotOK;
315 ehResult = OC_EH_ERROR;
318 else if (ehRequest->resource != Light.handle)
320 //Let's this app not supporting DELETE on some resources so
321 //consider the DELETE request is received for a non-support resource.
322 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
323 deleteResponse = responsePayloadDeleteResourceNotSupported;
324 ehResult = OC_EH_FORBIDDEN;
327 if (maxPayloadSize > strlen ((char *)deleteResponse))
329 strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
333 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
335 ehResult = OC_EH_ERROR;
341 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest,
342 char *payload, uint16_t maxPayloadSize)
344 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
346 const char* response = NULL;
347 response = responsePayloadResourceDoesNotExist;
349 if ( (ehRequest != NULL) &&
350 (maxPayloadSize > strlen ((char *)response)) )
352 strncpy((char *)payload, response, strlen((char *)response));
356 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
360 return OC_EH_RESOURCE_DELETED;
363 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
365 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
366 ehRequest->obsInfo.obsId);
367 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
369 if (interestedObservers[i].valid == false)
371 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
372 interestedObservers[i].valid = true;
373 gLightUnderObservation = 1;
379 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
381 bool clientStillObserving = false;
383 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
384 ehRequest->obsInfo.obsId);
385 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
387 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
389 interestedObservers[i].valid = false;
391 if (interestedObservers[i].valid == true)
393 // Even if there is one single client observing we continue notifying entity handler
394 clientStillObserving = true;
397 if (clientStillObserving == false)
398 gLightUnderObservation = 0;
401 OCEntityHandlerResult
402 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
403 OCEntityHandlerRequest *entityHandlerRequest, char* uri)
405 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
407 OCEntityHandlerResult ehResult = OC_EH_OK;
408 OCEntityHandlerResponse response;
409 char payload[MAX_RESPONSE_LENGTH] = {0};
412 if (!entityHandlerRequest)
414 OC_LOG (ERROR, TAG, "Invalid request pointer");
418 // Initialize certain response fields
419 response.numSendVendorSpecificHeaderOptions = 0;
420 memset(response.sendVendorSpecificHeaderOptions, 0,
421 sizeof response.sendVendorSpecificHeaderOptions);
422 memset(response.resourceUri, 0, sizeof response.resourceUri);
424 if (flag & OC_INIT_FLAG)
426 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
428 if (flag & OC_REQUEST_FLAG)
430 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
431 if (entityHandlerRequest->resource == NULL)
433 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
434 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest,
435 payload, sizeof(payload) - 1);
437 else if (OC_REST_GET == entityHandlerRequest->method)
439 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
440 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
442 else if (OC_REST_PUT == entityHandlerRequest->method)
444 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
445 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
447 else if (OC_REST_DELETE == entityHandlerRequest->method)
449 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
450 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
454 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
455 entityHandlerRequest->method);
456 ehResult = OC_EH_ERROR;
459 // If the result isn't an error or forbidden, send response
460 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
462 // Format the response. Note this requires some info about the request
463 response.requestHandle = entityHandlerRequest->requestHandle;
464 response.resourceHandle = entityHandlerRequest->resource;
465 response.ehResult = ehResult;
466 response.payload = (unsigned char *)payload;
467 response.payloadSize = strlen(payload);
468 // Indicate that response is NOT in a persistent buffer
469 response.persistentBufferFlag = 0;
472 if (OCDoResponse(&response) != OC_STACK_OK)
474 OC_LOG(ERROR, TAG, "Error sending response");
475 ehResult = OC_EH_ERROR;
479 if (flag & OC_OBSERVE_FLAG)
481 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
482 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
484 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
486 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
488 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
495 OCEntityHandlerResult
496 OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
497 OCEntityHandlerRequest *entityHandlerRequest)
499 // This is callback is associated with the 2 presence notification
500 // resources. They are non-operational.
504 OCEntityHandlerResult
505 OCEntityHandlerCb (OCEntityHandlerFlag flag,
506 OCEntityHandlerRequest *entityHandlerRequest)
508 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
510 OCEntityHandlerResult ehResult = OC_EH_OK;
511 OCEntityHandlerResponse response;
512 char payload[MAX_RESPONSE_LENGTH] = {0};
515 if (!entityHandlerRequest)
517 OC_LOG (ERROR, TAG, "Invalid request pointer");
521 // Initialize certain response fields
522 response.numSendVendorSpecificHeaderOptions = 0;
523 memset(response.sendVendorSpecificHeaderOptions,
524 0, sizeof response.sendVendorSpecificHeaderOptions);
525 memset(response.resourceUri, 0, sizeof response.resourceUri);
527 if (flag & OC_INIT_FLAG)
529 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
531 if (flag & OC_REQUEST_FLAG)
533 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
534 if (OC_REST_GET == entityHandlerRequest->method)
536 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
537 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
539 else if (OC_REST_PUT == entityHandlerRequest->method)
541 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
542 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
544 else if (OC_REST_POST == entityHandlerRequest->method)
546 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
547 ehResult = ProcessPostRequest (entityHandlerRequest,
548 &response, payload, sizeof(payload) - 1);
550 else if (OC_REST_DELETE == entityHandlerRequest->method)
552 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
553 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
557 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
558 entityHandlerRequest->method);
561 // If the result isn't an error or forbidden, send response
562 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
564 // Format the response. Note this requires some info about the request
565 response.requestHandle = entityHandlerRequest->requestHandle;
566 response.resourceHandle = entityHandlerRequest->resource;
567 response.ehResult = ehResult;
568 response.payload = (unsigned char *)payload;
569 response.payloadSize = strlen(payload);
570 // Indicate that response is NOT in a persistent buffer
571 response.persistentBufferFlag = 0;
573 // Handle vendor specific options
574 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
575 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
577 OC_LOG (INFO, TAG, "Received vendor specific options");
579 OCHeaderOption * rcvdOptions =
580 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
581 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
583 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
585 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
586 ((OCHeaderOption)rcvdOptions[i]).optionID );
587 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
588 ((OCHeaderOption)rcvdOptions[i]).optionLength);
591 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
592 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
593 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
594 sendOptions[0].protocolID = OC_COAP_ID;
595 sendOptions[0].optionID = 2248;
596 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
597 sendOptions[0].optionLength = 10;
598 sendOptions[1].protocolID = OC_COAP_ID;
599 sendOptions[1].optionID = 2600;
600 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
601 sendOptions[1].optionLength = 10;
602 response.numSendVendorSpecificHeaderOptions = 2;
606 if (OCDoResponse(&response) != OC_STACK_OK)
608 OC_LOG(ERROR, TAG, "Error sending response");
609 ehResult = OC_EH_ERROR;
613 if (flag & OC_OBSERVE_FLAG)
615 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
617 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
619 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
620 ProcessObserveRegister (entityHandlerRequest);
622 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
624 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
625 ProcessObserveDeregister (entityHandlerRequest);
632 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
633 void handleSigInt(int signum)
635 if (signum == SIGINT)
641 void *ChangeLightRepresentation (void *param)
644 OCStackResult result = OC_STACK_ERROR;
647 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
648 OCObservationId obsNotify[numNotifies];
654 if (gLightUnderObservation)
656 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
657 if (gObserveNotifyType == 1)
659 // Notify list of observers. Alternate observers on the list will be notified.
661 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
663 if (interestedObservers[i].valid == true)
665 obsNotify[j] = interestedObservers[i].observationId;
670 cJSON *json = cJSON_CreateObject();
672 cJSON_AddStringToObject(json,"href",gResourceUri);
673 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
674 cJSON_AddStringToObject(format, "state", (char *) (Light.state ? "on":"off"));
675 cJSON_AddNumberToObject(format, "power", Light.power);
676 char * obsResp = cJSON_Print(json);
678 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
679 (unsigned char *)obsResp, OC_NA_QOS);
682 else if (gObserveNotifyType == 0)
684 // Notifying all observers
685 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
686 if (OC_STACK_NO_OBSERVERS == result)
689 "=======> No more observers exist, stop sending observations");
690 gLightUnderObservation = 0;
695 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
699 if(stopPresenceCount > 0)
701 OC_LOG_V(INFO, TAG, "================ presence count %d", stopPresenceCount);
703 if(!stopPresenceCount--)
705 OC_LOG(INFO, TAG, "================ stopping presence");
713 void *presenceNotificationGenerator(void *param)
717 OCDoHandle presenceNotificationHandles[numPresenceResources];
718 OCStackResult res = OC_STACK_OK;
720 std::array<std::string, numPresenceResources> presenceNotificationResources { {
721 std::string("core.fan"),
722 std::string("core.led") } };
723 std::array<std::string, numPresenceResources> presenceNotificationUris { {
724 std::string("/a/fan"),
725 std::string("/a/led") } };
727 for(int i=0; i<numPresenceResources; i++)
729 if(res == OC_STACK_OK)
732 res = OCCreateResource(&presenceNotificationHandles[i],
733 presenceNotificationResources.at(i).c_str(),
735 presenceNotificationUris.at(i).c_str(),
736 OCNOPEntityHandlerCb,
737 OC_DISCOVERABLE|OC_OBSERVABLE);
739 if(res != OC_STACK_OK)
741 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
742 "%s with result %s.", presenceNotificationResources.at(i).c_str(),
748 for(int i=0; i<numPresenceResources; i++)
750 if(res == OC_STACK_OK)
752 res = OCDeleteResource(presenceNotificationHandles[i]);
754 if(res != OC_STACK_OK)
756 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
757 "resource %s.", presenceNotificationResources.at(i).c_str());
764 static void PrintUsage()
766 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
767 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
768 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
771 int main(int argc, char* argv[])
774 pthread_t threadId_presence;
777 while ((opt = getopt(argc, argv, "o:")) != -1)
782 gObserveNotifyType = atoi(optarg);
790 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
796 OC_LOG(DEBUG, TAG, "OCServer is starting...");
798 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
800 OC_LOG(ERROR, TAG, "OCStack init error");
804 if (OCStartPresence(0) != OC_STACK_OK)
806 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
811 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb);
813 OCStackResult deviceResult = SetDeviceInfo(contentType, dateOfManufacture, deviceName,
814 deviceUUID, firmwareVersion, hostName, manufacturerName,
815 manufacturerUrl, modelNumber, platformVersion, supportUrl, version);
817 if (deviceResult != OC_STACK_OK)
819 OC_LOG(INFO, TAG, "Device Registration failed!");
823 deviceResult = OCSetDeviceInfo(deviceInfo);
825 if (deviceResult != OC_STACK_OK)
827 OC_LOG(INFO, TAG, "Device Registration failed!");
832 * Declare and create the example resource: Light
834 createLightResource(gResourceUri, &Light);
836 // Initialize observations data structure for the resource
837 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
839 interestedObservers[i].valid = false;
843 * Create a thread for changing the representation of the Light
845 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
848 * Create a thread for generating changes that cause presence notifications
849 * to be sent to clients
851 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
853 // Break from loop with Ctrl-C
854 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
856 signal(SIGINT, handleSigInt);
859 if (OCProcess() != OC_STACK_OK)
861 OC_LOG(ERROR, TAG, "OCStack process error");
869 * Cancel the Light thread and wait for it to terminate
871 pthread_cancel(threadId);
872 pthread_join(threadId, NULL);
873 pthread_cancel(threadId_presence);
874 pthread_join(threadId_presence, NULL);
876 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
878 if (OCStop() != OC_STACK_OK)
880 OC_LOG(ERROR, TAG, "OCStack process error");
886 int createLightResource (char *uri, LightResource *lightResource)
890 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
894 lightResource->state = false;
895 lightResource->power= 0;
896 OCStackResult res = OCCreateResource(&(lightResource->handle),
901 OC_DISCOVERABLE|OC_OBSERVABLE);
902 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
907 void DeleteDeviceInfo()
909 free(deviceInfo.contentType);
910 free(deviceInfo.dateOfManufacture);
911 free(deviceInfo.deviceName);
912 free(deviceInfo.deviceUUID);
913 free(deviceInfo.firmwareVersion);
914 free(deviceInfo.hostName);
915 free(deviceInfo.manufacturerName);
916 free(deviceInfo.manufacturerUrl);
917 free(deviceInfo.modelNumber);
918 free(deviceInfo.platformVersion);
919 free(deviceInfo.supportUrl);
920 free(deviceInfo.version);
923 bool DuplicateString(char** targetString, const char* sourceString)
931 *targetString = (char *) malloc(strlen(sourceString) + 1);
934 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
941 OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture,
942 const char *deviceName, const char *deviceUUID, const char *firmwareVersion,
943 const char *hostName, const char *manufacturerName, const char *manufacturerUrl,
944 const char *modelNumber, const char *platformVersion, const char *supportUrl,
950 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH))
952 return OC_STACK_INVALID_PARAM;
955 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH))
957 return OC_STACK_INVALID_PARAM;
960 if(!DuplicateString(&deviceInfo.contentType, contentType))
965 if(!DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture))
970 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
975 if(!DuplicateString(&deviceInfo.deviceUUID, deviceUUID))
980 if(!DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion))
985 if(!DuplicateString(&deviceInfo.hostName, hostName))
990 if(!DuplicateString(&deviceInfo.manufacturerName, manufacturerName))
995 if(!DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl))
1000 if(!DuplicateString(&deviceInfo.modelNumber, modelNumber))
1005 if(!DuplicateString(&deviceInfo.platformVersion, platformVersion))
1010 if(!DuplicateString(&deviceInfo.supportUrl, supportUrl))
1015 if(!DuplicateString(&deviceInfo.version, version))
1026 return OC_STACK_ERROR;