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[] = "{App determines payload: Delete Resource operation succeeded.}";
60 const char responsePayloadDeleteNotOK[] = "{App determines payload: Delete Resource operation failed.}";
61 const char responsePayloadResourceDoesNotExist[] = "{App determines payload: The resource does not exist.}";
62 const char responsePayloadDeleteResourceNotSupported[] =
63 "{App determines payload: The request is received for a non-support resource.}";
66 char *gResourceUri= (char *)"/a/light";
67 const char *contentType = "myContentType";
68 const char *dateOfManufacture = "myDateOfManufacture";
69 const char *deviceName = "myDeviceName";
70 const char *deviceUUID = "myDeviceUUID";
71 const char *firmwareVersion = "myFirmwareVersion";
72 const char *hostName = "myHostName";
73 const char *manufacturerName = "myManufacturerNa";
74 const char *manufacturerUrl = "myManufacturerUrl";
75 const char *modelNumber = "myModelNumber";
76 const char *platformVersion = "myPlatformVersion";
77 const char *supportUrl = "mySupportUrl";
78 const char *version = "myVersion";
80 OCDeviceInfo deviceInfo;
82 static uint16_t OC_WELL_KNOWN_PORT = 5683;
84 //This function takes the request as an input and returns the response
86 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
88 cJSON *json = cJSON_CreateObject();
91 LightResource *currLightResource = &Light;
93 if (ehRequest->resource == gLightInstance[0].handle)
95 currLightResource = &gLightInstance[0];
96 gResourceUri = (char *) "a/light/0";
98 else if (ehRequest->resource == gLightInstance[1].handle)
100 currLightResource = &gLightInstance[1];
101 gResourceUri = (char *) "a/light/1";
104 if(OC_REST_PUT == ehRequest->method)
106 cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
107 currLightResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring,
109 currLightResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
110 cJSON_Delete(putJson);
113 cJSON_AddStringToObject(json,"href",gResourceUri);
114 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
115 cJSON_AddStringToObject(format, "state", (char *) (currLightResource->state ? "on":"off"));
116 cJSON_AddNumberToObject(format, "power", currLightResource->power);
118 jsonResponse = cJSON_Print(json);
124 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
126 OCEntityHandlerResult ehResult;
127 char *getResp = constructJsonResponse(ehRequest);
129 if (maxPayloadSize > strlen ((char *)getResp))
131 strncpy(payload, getResp, strlen((char *)getResp));
136 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
138 ehResult = OC_EH_ERROR;
146 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
148 OCEntityHandlerResult ehResult;
149 char *putResp = constructJsonResponse(ehRequest);
151 if (maxPayloadSize > strlen ((char *)putResp))
153 strncpy(payload, putResp, strlen((char *)putResp));
158 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
160 ehResult = OC_EH_ERROR;
168 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
170 OCEntityHandlerResult ehResult = OC_EH_OK;
171 char *respPLPost_light = NULL;
176 * The entity handler determines how to process a POST request.
177 * Per the REST paradigm, POST can also be used to update representation of existing
178 * resource or create a new resource.
179 * In the sample below, if the POST is for /a/light then a new instance of the Light
180 * resource is created with default representation (if representation is included in
181 * POST payload it can be used as initial values) as long as the instance is
182 * lesser than max new instance count. Once max instance count is reached, POST on
183 * /a/light updated the representation of /a/light (just like PUT)
186 if (ehRequest->resource == Light.handle)
188 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
190 // Create new Light instance
191 char newLightUri[URI_MAXSIZE];
192 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
194 json = cJSON_CreateObject();
195 cJSON_AddStringToObject(json,"href",gResourceUri);
196 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
197 cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
199 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
201 OC_LOG (INFO, TAG, "Created new Light instance\n");
202 gLightInstance[gCurrLightInstance].state = 0;
203 gLightInstance[gCurrLightInstance].power = 0;
204 gCurrLightInstance++;
205 respPLPost_light = cJSON_Print(json);
206 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
207 ehResult = OC_EH_RESOURCE_CREATED;
214 // Update repesentation of /a/light
217 respPLPost_light = constructJsonResponse(ehRequest);
222 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
224 if (ehRequest->resource == gLightInstance[i].handle)
226 gLightInstance[i].state = true;
227 gLightInstance[i].power = 22;
230 respPLPost_light = constructJsonResponse(ehRequest);
235 respPLPost_light = constructJsonResponse(ehRequest);
241 if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
243 strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
247 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
249 ehResult = OC_EH_ERROR;
252 free(respPLPost_light);
256 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
258 if(ehRequest == NULL)
260 OC_LOG(INFO, TAG, "The ehRequest is NULL");
263 OCEntityHandlerResult ehResult = OC_EH_OK;
265 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
268 * In the sample below, the application will:
269 * 1a. pass the delete request to the c stack
270 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
271 * (e.g. send observers notification, remove observers...)
272 * 1c. the c stack returns with the result whether the request is fullfilled.
273 * 2. optionally, app removes observers out of its array 'interestedObservers'
276 const char* deleteResponse = NULL;
278 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
280 //Step 1: Ask stack to do the work.
281 OCStackResult result = OCDeleteResource(ehRequest->resource);
283 if (result == OC_STACK_OK)
285 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
287 deleteResponse = responsePayloadDeleteOk;
289 //Step 2: clear observers who wanted to observe this resource at the app level.
290 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
292 if (interestedObservers[i].resourceHandle == ehRequest->resource)
294 interestedObservers[i].valid = false;
295 interestedObservers[i].observationId = 0;
296 interestedObservers[i].resourceHandle = NULL;
300 else if (result == OC_STACK_NO_RESOURCE)
302 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
303 deleteResponse = responsePayloadResourceDoesNotExist;
304 ehResult = OC_EH_RESOURCE_DELETED;
308 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
309 deleteResponse = responsePayloadDeleteNotOK;
310 ehResult = OC_EH_ERROR;
313 else if (ehRequest->resource != Light.handle)
315 //Let's this app not supporting DELETE on some resources so
316 //consider the DELETE request is received for a non-support resource.
317 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
318 deleteResponse = responsePayloadDeleteResourceNotSupported;
319 ehResult = OC_EH_FORBIDDEN;
322 if (maxPayloadSize > strlen ((char *)deleteResponse))
324 strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
328 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
330 ehResult = OC_EH_ERROR;
336 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
338 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
340 const char* response = NULL;
341 response = responsePayloadResourceDoesNotExist;
343 if ( (ehRequest != NULL) &&
344 (maxPayloadSize > strlen ((char *)response)) )
346 strncpy((char *)payload, response, strlen((char *)response));
350 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
354 return OC_EH_RESOURCE_DELETED;
357 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
359 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
360 ehRequest->obsInfo.obsId);
361 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
363 if (interestedObservers[i].valid == false)
365 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
366 interestedObservers[i].valid = true;
367 gLightUnderObservation = 1;
373 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
375 bool clientStillObserving = false;
377 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
378 ehRequest->obsInfo.obsId);
379 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
381 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
383 interestedObservers[i].valid = false;
385 if (interestedObservers[i].valid == true)
387 // Even if there is one single client observing we continue notifying entity handler
388 clientStillObserving = true;
391 if (clientStillObserving == false)
392 gLightUnderObservation = 0;
395 OCEntityHandlerResult
396 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
397 OCEntityHandlerRequest *entityHandlerRequest, char* uri)
399 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
401 OCEntityHandlerResult ehResult = OC_EH_OK;
402 OCEntityHandlerResponse response;
403 char payload[MAX_RESPONSE_LENGTH] = {0};
406 if (!entityHandlerRequest)
408 OC_LOG (ERROR, TAG, "Invalid request pointer");
412 // Initialize certain response fields
413 response.numSendVendorSpecificHeaderOptions = 0;
414 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
415 memset(response.resourceUri, 0, sizeof response.resourceUri);
417 if (flag & OC_INIT_FLAG)
419 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
421 if (flag & OC_REQUEST_FLAG)
423 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
424 if (entityHandlerRequest->resource == NULL) {
425 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
426 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
428 else if (OC_REST_GET == entityHandlerRequest->method)
430 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
431 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
433 else if (OC_REST_PUT == entityHandlerRequest->method)
435 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
436 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
438 else if (OC_REST_DELETE == entityHandlerRequest->method)
440 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
441 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
445 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
446 entityHandlerRequest->method);
447 ehResult = OC_EH_ERROR;
450 // If the result isn't an error or forbidden, send response
451 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
453 // Format the response. Note this requires some info about the request
454 response.requestHandle = entityHandlerRequest->requestHandle;
455 response.resourceHandle = entityHandlerRequest->resource;
456 response.ehResult = ehResult;
457 response.payload = (unsigned char *)payload;
458 response.payloadSize = strlen(payload);
459 // Indicate that response is NOT in a persistent buffer
460 response.persistentBufferFlag = 0;
463 if (OCDoResponse(&response) != OC_STACK_OK)
465 OC_LOG(ERROR, TAG, "Error sending response");
466 ehResult = OC_EH_ERROR;
470 if (flag & OC_OBSERVE_FLAG)
472 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
473 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
475 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
477 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
479 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
486 OCEntityHandlerResult
487 OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
488 OCEntityHandlerRequest *entityHandlerRequest)
490 // This is callback is associated with the 2 presence notification
491 // resources. They are non-operational.
495 OCEntityHandlerResult
496 OCEntityHandlerCb (OCEntityHandlerFlag flag,
497 OCEntityHandlerRequest *entityHandlerRequest)
499 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
501 OCEntityHandlerResult ehResult = OC_EH_OK;
502 OCEntityHandlerResponse response;
503 char payload[MAX_RESPONSE_LENGTH] = {0};
506 if (!entityHandlerRequest)
508 OC_LOG (ERROR, TAG, "Invalid request pointer");
512 // Initialize certain response fields
513 response.numSendVendorSpecificHeaderOptions = 0;
514 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
515 memset(response.resourceUri, 0, sizeof response.resourceUri);
517 if (flag & OC_INIT_FLAG)
519 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
521 if (flag & OC_REQUEST_FLAG)
523 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
524 if (OC_REST_GET == entityHandlerRequest->method)
526 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
527 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
529 else if (OC_REST_PUT == entityHandlerRequest->method)
531 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
532 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
534 else if (OC_REST_POST == entityHandlerRequest->method)
536 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
537 ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
539 else if (OC_REST_DELETE == entityHandlerRequest->method)
541 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
542 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
546 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
547 entityHandlerRequest->method);
550 // If the result isn't an error or forbidden, send response
551 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
553 // Format the response. Note this requires some info about the request
554 response.requestHandle = entityHandlerRequest->requestHandle;
555 response.resourceHandle = entityHandlerRequest->resource;
556 response.ehResult = ehResult;
557 response.payload = (unsigned char *)payload;
558 response.payloadSize = strlen(payload);
559 // Indicate that response is NOT in a persistent buffer
560 response.persistentBufferFlag = 0;
562 // Handle vendor specific options
563 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
564 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
566 OC_LOG (INFO, TAG, "Received vendor specific options");
568 OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
569 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
571 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
573 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
574 ((OCHeaderOption)rcvdOptions[i]).optionID );
575 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
576 ((OCHeaderOption)rcvdOptions[i]).optionLength);
579 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
580 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
581 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
582 sendOptions[0].protocolID = OC_COAP_ID;
583 sendOptions[0].optionID = 2248;
584 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
585 sendOptions[0].optionLength = 10;
586 sendOptions[1].protocolID = OC_COAP_ID;
587 sendOptions[1].optionID = 2600;
588 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
589 sendOptions[1].optionLength = 10;
590 response.numSendVendorSpecificHeaderOptions = 2;
594 if (OCDoResponse(&response) != OC_STACK_OK)
596 OC_LOG(ERROR, TAG, "Error sending response");
597 ehResult = OC_EH_ERROR;
601 if (flag & OC_OBSERVE_FLAG)
603 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
605 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
607 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
608 ProcessObserveRegister (entityHandlerRequest);
610 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
612 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
613 ProcessObserveDeregister (entityHandlerRequest);
620 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
621 void handleSigInt(int signum) {
622 if (signum == SIGINT) {
627 void *ChangeLightRepresentation (void *param)
630 OCStackResult result = OC_STACK_ERROR;
633 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
634 OCObservationId obsNotify[numNotifies];
640 if (gLightUnderObservation)
642 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
643 if (gObserveNotifyType == 1)
645 // Notify list of observers. Alternate observers on the list will be notified.
647 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
649 if (interestedObservers[i].valid == true)
651 obsNotify[j] = interestedObservers[i].observationId;
656 cJSON *json = cJSON_CreateObject();
658 cJSON_AddStringToObject(json,"href",gResourceUri);
659 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
660 cJSON_AddStringToObject(format, "state", (char *) (Light.state ? "on":"off"));
661 cJSON_AddNumberToObject(format, "power", Light.power);
662 char * obsResp = cJSON_Print(json);
664 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
665 (unsigned char *)obsResp, OC_NA_QOS);
668 else if (gObserveNotifyType == 0)
670 // Notifying all observers
671 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
672 if (OC_STACK_NO_OBSERVERS == result)
675 "=======> No more observers exist, stop sending observations");
676 gLightUnderObservation = 0;
681 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
685 if(stopPresenceCount > 0)
687 OC_LOG_V(INFO, TAG, "================ presence count %d", stopPresenceCount);
689 if(!stopPresenceCount--)
691 OC_LOG(INFO, TAG, "================ stopping presence");
699 void *presenceNotificationGenerator(void *param)
703 OCDoHandle presenceNotificationHandles[numPresenceResources];
704 OCStackResult res = OC_STACK_OK;
706 std::array<std::string, numPresenceResources> presenceNotificationResources { {
707 std::string("core.fan"),
708 std::string("core.led") } };
709 std::array<std::string, numPresenceResources> presenceNotificationUris { {
710 std::string("/a/fan"),
711 std::string("/a/led") } };
713 for(int i=0; i<numPresenceResources; i++)
715 if(res == OC_STACK_OK)
718 res = OCCreateResource(&presenceNotificationHandles[i],
719 presenceNotificationResources.at(i).c_str(),
721 presenceNotificationUris.at(i).c_str(),
722 OCNOPEntityHandlerCb,
723 OC_DISCOVERABLE|OC_OBSERVABLE);
725 if(res != OC_STACK_OK)
727 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
728 "%s with result %s.", presenceNotificationResources.at(i).c_str(),
734 for(int i=0; i<numPresenceResources; i++)
736 if(res == OC_STACK_OK)
738 res = OCDeleteResource(presenceNotificationHandles[i]);
740 if(res != OC_STACK_OK)
742 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
743 "resource %s.", presenceNotificationResources.at(i).c_str());
750 static void PrintUsage()
752 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
753 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
754 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
757 int main(int argc, char* argv[])
759 uint8_t addr[20] = {0};
760 uint8_t* paddr = NULL;
761 uint16_t port = OC_WELL_KNOWN_PORT;
762 uint8_t ifname[] = "eth0";
764 pthread_t threadId_presence;
767 while ((opt = getopt(argc, argv, "o:")) != -1)
772 gObserveNotifyType = atoi(optarg);
780 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
786 OC_LOG(DEBUG, TAG, "OCServer is starting...");
787 /*Get Ip address on defined interface and initialize coap on it with random port number
788 * this port number will be used as a source port in all coap communications*/
789 if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
790 sizeof(addr)) == ERR_SUCCESS)
792 OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
796 if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) {
797 OC_LOG(ERROR, TAG, "OCStack init error");
801 if (OCStartPresence(0) != OC_STACK_OK) {
802 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
807 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb);
809 OCStackResult deviceResult = SetDeviceInfo(contentType, dateOfManufacture, deviceName,
810 deviceUUID, firmwareVersion, hostName, manufacturerName,
811 manufacturerUrl, modelNumber, platformVersion, supportUrl, version);
813 if (deviceResult != OC_STACK_OK)
815 OC_LOG(INFO, TAG, "Device Registration failed!");
819 deviceResult = OCSetDeviceInfo(deviceInfo);
821 if (deviceResult != OC_STACK_OK)
823 OC_LOG(INFO, TAG, "Device Registration failed!");
828 * Declare and create the example resource: Light
830 createLightResource(gResourceUri, &Light);
832 // Initialize observations data structure for the resource
833 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
835 interestedObservers[i].valid = false;
839 * Create a thread for changing the representation of the Light
841 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
844 * Create a thread for generating changes that cause presence notifications
845 * to be sent to clients
847 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
849 // Break from loop with Ctrl-C
850 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
852 signal(SIGINT, handleSigInt);
854 if (OCProcess() != OC_STACK_OK) {
855 OC_LOG(ERROR, TAG, "OCStack process error");
863 * Cancel the Light thread and wait for it to terminate
865 pthread_cancel(threadId);
866 pthread_join(threadId, NULL);
867 pthread_cancel(threadId_presence);
868 pthread_join(threadId_presence, NULL);
870 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
872 if (OCStop() != OC_STACK_OK) {
873 OC_LOG(ERROR, TAG, "OCStack process error");
879 int createLightResource (char *uri, LightResource *lightResource)
883 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
887 lightResource->state = false;
888 lightResource->power= 0;
889 OCStackResult res = OCCreateResource(&(lightResource->handle),
894 OC_DISCOVERABLE|OC_OBSERVABLE);
895 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
900 void DeleteDeviceInfo()
902 free(deviceInfo.contentType);
903 free(deviceInfo.dateOfManufacture);
904 free(deviceInfo.deviceName);
905 free(deviceInfo.deviceUUID);
906 free(deviceInfo.firmwareVersion);
907 free(deviceInfo.hostName);
908 free(deviceInfo.manufacturerName);
909 free(deviceInfo.manufacturerUrl);
910 free(deviceInfo.modelNumber);
911 free(deviceInfo.platformVersion);
912 free(deviceInfo.supportUrl);
913 free(deviceInfo.version);
916 bool DuplicateString(char** targetString, const char* sourceString)
924 *targetString = (char *) malloc(strlen(sourceString) + 1);
928 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
935 OCStackResult SetDeviceInfo(const char *contentType, const char *dateOfManufacture,
936 const char *deviceName, const char *deviceUUID, const char *firmwareVersion,
937 const char *hostName, const char *manufacturerName, const char *manufacturerUrl,
938 const char *modelNumber, const char *platformVersion, const char *supportUrl,
944 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH))
946 return OC_STACK_INVALID_PARAM;
949 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH))
951 return OC_STACK_INVALID_PARAM;
954 if(!DuplicateString(&deviceInfo.contentType, contentType))
959 if(!DuplicateString(&deviceInfo.dateOfManufacture, dateOfManufacture))
964 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
969 if(!DuplicateString(&deviceInfo.deviceUUID, deviceUUID))
974 if(!DuplicateString(&deviceInfo.firmwareVersion, firmwareVersion))
979 if(!DuplicateString(&deviceInfo.hostName, hostName))
984 if(!DuplicateString(&deviceInfo.manufacturerName, manufacturerName))
989 if(!DuplicateString(&deviceInfo.manufacturerUrl, manufacturerUrl))
994 if(!DuplicateString(&deviceInfo.modelNumber, modelNumber))
999 if(!DuplicateString(&deviceInfo.platformVersion, platformVersion))
1004 if(!DuplicateString(&deviceInfo.supportUrl, supportUrl))
1009 if(!DuplicateString(&deviceInfo.version, version))
1020 return OC_STACK_ERROR;